您需要做的就是声明RB
不带: public RA
(哦,还要添加;
到类定义的末尾):
class RA;
class A {
public:
virtual RA* Foo();
};
class RB;
class B {
public:
virtual RB* Foo();
};
class RA {};
class RB : public RA {};
int main ()
{
return 0;
}
但是,这不能解决user1332054的答案中很好描述的特定问题。
其他一些答案似乎表明我想消除一些误解:
向前声明甚至是有用的当我们知道不太可能包含该定义时,。这使我们可以在我们的库中进行很多类型推导,使它们与许多其他已建立的库兼容,而无需包含它们。包含库会不必要地导致过多的嵌套包含,这可能会激增编译时间。良好的做法是在适当的时候使您的代码兼容,并包括尽可能少的代码。
通常,您可以使用指向仅已声明但未定义的类的指针来定义一个类。例:
struct B;
struct A
{
B * b_;
B * foo ()
{
return b_;
}
B & foo (B * b)
{
return *b;
}
};
int main ()
{
return 0;
}
上面的编译很好,因为编译器不需要了解B。
一个示例,可能很难意识到编译器需要更多信息:
struct B;
struct A
{
B * foo ()
{
return new B;
}
};
上面的问题是因为new B
调用了B::B()
尚未定义的构造函数。也:
struct B;
struct A
{
void foo (B b) {}
};
这里foo
必须为调用复制构造函数b
,该构造函数也尚未定义。最后:
struct B;
struct A
{
B b;
};
在这里,我们已A
使用默认构造函数隐式定义,该默认构造函数调用调用其成员的默认构造函数,该成员b
尚未定义。我认为你说对了。
因此,对于由user1332054描述的更普遍的问题,老实说,我不明白为什么无法在继承的虚函数中使用指向未定义类的指针。
不过,更广泛地说,我认为通过定义类而不是仅声明类,使自己变得更加困难。这是一个示例,DoCleverStuff
在您完全定义任何类之前,请先处理库中的类:
class RA;
class RB;
class A;
class B;
template <class T>
struct is_type_A
{
static constexpr bool value = false;
};
template <>
struct is_type_A <A>
{
static constexpr bool value = true;
};
template <class T>
struct is_type_B
{
static constexpr bool value = false;
};
template <>
struct is_type_B <B>
{
static constexpr bool value = true;
};
#include <type_traits>
template<class T>
typename std::enable_if<is_type_A<T>::value, RA *>::type
DoCleverStuff (T & t)
{
return t.fooRet();
}
template<class T>
typename std::enable_if<is_type_B<T>::value, RB *>::type
DoCleverStuff (T & t)
{
return t.fooRet();
}
class RA
{
int x;
};
class RB : public RA
{
int y;
};
class A
{
public:
virtual RA * fooRet()
{
return new RA;
}
};
class B : public A
{
public:
virtual RB * fooRet()
{
return new RB;
}
};
int main ()
{
A a;
RA * ra = DoCleverStuff(a);
B b;
RB * rb = DoCleverStuff(b);
delete ra;
delete rb;
return 0;
}