Two classes referencing each other

Started by
7 comments, last by Swarmer 15 years, 8 months ago
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.
Advertisement
Use a forward declaration of the class

ClassOne.h:
class ClassTwo;//lets the compiler know there is a class by that nameclass ClassOne{    //stuff    ClassTwo* ptr;};
ClassTwo.h:
class ClassOne;class ClassTwo{    //stuff    ClassOne* ptr;};
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.
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?
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.
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?
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 declarationclass ClassTwo;class ClassOne{private:     ClassTwo* m_pkClassTwo;public:     ClassOne();};


#pragma once// Forward declarationclass 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.
Okay, with that method, I think I can manage (OMG PUN!). I can work with it.

Thanks for everyone's help!
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.

This topic is closed to new replies.

Advertisement