According to http://msdn.microsoft.com/en-us/library/9ekhdcxs(v=vs.80).aspx,
C2079 can also occur if you attempt to declare an object on the stack of a type whose forward declaration is only in scope.
class A; class B { A a; // C2079 }; class A {};
Possible resolution:
class A; class C {}; class B { A * a; C c; }; class A {};
My question is how do I eliminate this error when I have the following situation:
class A; // Object
class B // Container
{
public:
typedef int SomeTypedef;
private:
A a; // C2079
};
class A {
void Foo(B::SomeTypedef);
};
I can't declare A before declaring B because A needs to use B's typedef, and I can't declare B before A because of this error.
One possible solution is to use a pointer to A instead of a stack variable, but I don't want a pointer (in this case).
Another solution is to not use typedef, or not to put it inside class B. But what if it belongs in B and I want not to pollute my project's namespace, as in B::SomeTypedef is a more appropriate name than SomeTypedef?
Your design is questionable, although perhaps nested classes is what you intend:
class B {
public:
typedef int SomeTypedef;
private:
class A {
void Foo(SomeTypedef);
};
A a;
};
If not, this can also be solved with another class which is common in CRTP code.
template<typename T>
struct foo;
class A;
class B;
template<>
struct foo<B> {
typedef int SomeTypedef;
};
class A {
void Foo(foo<B>::SomeTypedef);
};
class B : foo<B> {
private:
A a;
};
Or you can use another namespace.
Another method is use an intermediate class, plus pointers, its more long, but, it works:
This is header file, ( yes I know, "*.hpp" extension is not standard ):
class ForwardClass {
public:
virtual void DoSomething();
};
class ContainerClass {
ForwardClass* Item;
/* constructor */ ContainerClass();
/* destructor */ ~ContainerClass();
};
class RealClass: ForwardClass {
/* override */ virtual void DoSomething();
};
This is body file:
/* constructor */ ContainerClass::ContainerClass()
{
// create reference to forwaded class item
this.Item = new RealClass();
}
/* destructor */ ContainerClass::~ContainerClass()
{
// deletereference to forwaded class item
free this.Item();
}
void ForwardClass::DoSomething()
{
// ...
}
void RealClass::DoSomething()
{
// ...
}
Note:
I suggest to get used to apply pointers to variables, instead of direct fields, its may looks more difficult, at start, but, eventually allows to do more stuff.
It also prepare you to use "references" in case, one day you have to work with other programming languages.
Cheers.
Introduce the typedef where your design requires it, and then export it to wherever it makes the most sense for your user.
class A
{
public:
typedef int SomeTypedef;
void Foo(SomeTypedef);
};
class B
{
public:
typedef A::SomeTypedef SomeTypedef;
private:
A a;
};
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With