根据http://msdn.microsoft.com/en-us/library/9ekhdcxs(v=vs.80).aspx,
如果您尝试在前向声明仅在范围内的类型的堆栈上声明对象,也会发生C2079。
class A; class B { A a; // C2079 }; class A {};
可能的解决方案:
class A; class C {}; class B { A * a; C c; }; class A {};
我的问题是如何在遇到以下情况时消除此错误:
class A; // Object
class B // Container
{
public:
typedef int SomeTypedef;
private:
A a; // C2079
};
class A {
void Foo(B::SomeTypedef);
};
在声明B之前我无法声明A,因为A需要使用B的typedef,并且由于此错误,我无法在A之前声明B.
一种可能的解决方案是使用指向A而不是堆栈变量的指针,但我不想要指针(在这种情况下)。
另一个解决方案是不使用typedef,或者不将它放在B类中。但是如果它属于B并且我不想污染我的项目的命名空间,就像B :: SomeTypedef是一个比SomeTypedef更合适的名称?
答案 0 :(得分:3)
您的设计是有问题的,尽管可能是您想要的嵌套类:
class B {
public:
typedef int SomeTypedef;
private:
class A {
void Foo(SomeTypedef);
};
A a;
};
如果没有,这也可以通过CRTP代码中常见的另一个类来解决。
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;
};
或者您可以使用其他命名空间。
答案 1 :(得分:3)
另一种方法是使用中间类,加上指针,它更长,但是,它起作用:
这是头文件,(是的,我知道,“* .hpp”扩展名不是标准的):
class ForwardClass {
public:
virtual void DoSomething();
};
class ContainerClass {
ForwardClass* Item;
/* constructor */ ContainerClass();
/* destructor */ ~ContainerClass();
};
class RealClass: ForwardClass {
/* override */ virtual void DoSomething();
};
这是正文:
/* 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()
{
// ...
}
注意:
我建议习惯将指针应用于变量,而不是直接字段,在开始时它可能看起来更难,但最终还是可以做更多的事情。
它还准备你使用“引用”,以防有一天你必须使用其他编程语言。
干杯。
答案 2 :(得分:1)
介绍设计所需的typedef,然后将其导出到对用户最有意义的地方。
class A
{
public:
typedef int SomeTypedef;
void Foo(SomeTypedef);
};
class B
{
public:
typedef A::SomeTypedef SomeTypedef;
private:
A a;
};