Sign in to follow this  
Swarmer

Two classes referencing each other

Recommended Posts

I'm trying to make a WinForm application. I have 2 form classes. Both classes have (a pointer to) an instance of the other class. I just came back from using C# a ton and now I'm doing managed C++ so I'm kind of disoriented. I've tried every combination of #include and forward declarations and it's not working. Here is the beginning of class 1:
#pragma once

ref class Project::ClassTwo;

namespace Project {

using namespace stuff;
.
. // using
.

public ref class ClassOne : public System::Windows::Forms::Form
{
.
.
.
public:
classTwo^ classTwo;
.
.
.

And class two is identical:
#pragma once

ref class Project::ClassOne;

namespace Project {

using namespace stuff;
.
. // using
.

public ref class ClassTwo : public System::Windows::Forms::Form
{
.
.
.
public:
classOne^ classOne;
.
.
.

The #includes are in stdafx.h. The code does not compile; it can't seem to recognize one of the classes, depending on the order of the #includes I use. I'm pretty sure this is a beginners mistake, but I just can't visualize what I'm supposed to be doing.

Share this post


Link to post
Share on other sites
Use a forward declaration of the class

ClassOne.h:
class ClassTwo;//lets the compiler know there is a class by that name

class ClassOne{
//stuff
ClassTwo* ptr;
};
ClassTwo.h:
class ClassOne;

class ClassTwo{
//stuff
ClassOne* ptr;
};

Share this post


Link to post
Share on other sites
Try moving your forward declarations into the namespace.
i.e. change this:
ref class Project::ClassOne;
namespace Project {
to this:
namespace Project {
ref class ClassOne;


If that doesn't work, please post the actual compiler errors.

Share this post


Link to post
Share on other sites
Well, that gives me less errors than before, but it still doesn't work.

It says that it's undefined: "Error C2027: use of undefined type 'Project::ClassOne' "

This error occurs when I try to use it like classOne->method(). However, it works in Intellisense: autocomplete gives me the full list of methods.

The weird thing is that it doesn't happen on the other class. I think this is because the #include statement for it was second?

Anyways, this is what I think the problem is, but I don't know the solution: When I mouse over the line with the error, it says it's of type Project::ClassTwo::ClassOne instead of Project::ClassOne. Is looks like it's treating the forward declaration as a whole new class?

Share this post


Link to post
Share on other sites
Quote:
Original post by Swarmer
This error occurs when I try to use it like classOne->method(). However, it works in Intellisense: autocomplete gives me the full list of methods.
That's the problem then - you're trying to use the pointer to call a method before the compiler has a full definition of what methods that class has!

The forward declaration only lets you declare that you're going to be using a pointer of the forward-declared type - it doesn't let you actually use the pointer.


I assume that this line of code is contained in the header? If so, then just move it into a CPP file, after both of the #includes.

Share this post


Link to post
Share on other sites
Oh, oops. I didn't know there were technical differences between .h and .cpp files.

But this is all in an automatically generated header file for a WinForm. Do I really have to turn it into 2 files? :( That would be pretty messy to double all of my form files. But if that's the only way, then I guess I will. So there's no way to get a header file to use a pointer of another class?

Share this post


Link to post
Share on other sites
Well sorry to tell you but no, there's no valid way of using a class where the compiler does not know the full definition.

I'm a bit unsure you misunderstood Hodgman however. You can safely declare pointers to classes which have been forward declared, but not instantiate them nor dereference and use them. So it's perfectly valid for you to forward declare ClassOne in ClassTwo's header file and have ClassTwo contain a ClassOne pointer as long as ClassOne has been forward declared before ClassOne is used in ClassTwo. But you cannot use the ClassOne class before it's been included. This is normally done in the start of the using .cpp file. This all sounds really confusing but it's not really - I've provided a small example.


#pragma once

// Forward declaration
class ClassTwo;

class ClassOne
{
private:
ClassTwo* m_pkClassTwo;

public:
ClassOne();
};




#pragma once

// Forward declaration
class ClassOne;

class ClassTwo
{
private:
ClassOne* m_pkClassOne;

public:
ClassTwo();
};



These are the headers. So far there's no use of the pointers. This is done in the cpp file as shown below.


#include "ClassOne.h"

#include "ClassTwo.h" // <----------- This is the actual include so you can use the class.

ClassOne::ClassOne()
{
m_pkClassTwo = new ClassTwo;
}




This is obviously plain C++, I don't know managed c++ but I take it the concepts are the same. Hope this helped.

Share this post


Link to post
Share on other sites
By the way, how exactly do precompiled headers work again? What should I be putting in stdafx.h and .cpp, and where should I be including it? I read a bit about them but I'm still not sure; is it just a general file where all my #includes should go?

EDIT: Ha, I just realized that it automatically generated .cpp files for my forms too. I just didn't notice them way down there. Silly me. But yeah, my new question still stands, about stdafx.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this