I have two C++ classes such that:
Given that, my question is: how do I organize the sources/headers/forward declarations for this situation? Whatever I tried, it just doesn't compile to an object file.
One sequence is this:
class Class2;
class Class1
{
Class2 * c2;
public:
template<typename T> T DoSomething(T& X)
{
c2->Func();
return X;
};
void FuncFromClass1();
};
class Class2
{
int data;
public:
Class2() : data(0) {};
void Func();
friend void Class1::FuncFromClass1();
};
void Class2::Func()
{
int i;
}
void Class1::FuncFromClass1()
{
int j;
c2 = new Class2;
c2->data = 1;
}
Barks invalid use of incomplete type ‘class Class2’
because it doesn't recognize c2->Func();
.
The other one is:
class Class1;
class Class2
{
int data;
public:
Class2() : data(0) {};
void Func();
friend void Class1::FuncFromClass1();
};
class Class1
{
Class2 * c2;
public:
template<typename T> T DoSomething(T& X)
{
c2->Func();
return X;
};
void FuncFromClass1();
};
void Class2::Func()
{
int i;
}
void Class1::FuncFromClass1()
{
int j;
c2 = new Class2;
c2->data = 1;
}
Doesn't recognize friend void Class1::FuncFromClass1();
.
The compilation is tried as g++ -c -std=c++11 -Wall test.cpp
.
Note I'd rather not make Class1
as entire friend, rather want to keep only one of its methods as a friend to Class2
, if at all possible.
Also, I haven't tried the exact same example in Visual Studio in Windows, but saw an entirely isomorphic situation like the one described (within a bigger project) and no complaints came from VS as far as I recall. Is it unique to g++?
Move the implementation of the member function template where definition of Class2
is known.
class Class2;
class Class1
{
private:
Class2 * c2;
public:
// Delcare, don't define
template<typename T> T DoSomething(T& X);
void FuncFromClass1();
};
class Class2
{
private:
int data;
public:
Class2() : data(0) {};
void Func();
friend void Class1::FuncFromClass1();
};
// Define
template<typename T>
T Class1::DoSomething(T& X)
{
c2->Func();
return X;
};
Note that the proposed solution is simple if both classes are defined in one .h file. If the classes are defined in separate .h files, things get a little bit more complex. You'll have to make sure that the .h file where Class1::DoSomething()
is defined is #include
d in every .cpp file where you want to use Class1::DoSomething()
.