forward声明是否完全消除了对指针类型的任何#include的需要



让我们假设我们有一个源文件a.cpp,在那里我们转发声明了一个类型ClassB,然后我们继续使用指向ClassB的指针,而不包括文件B.cpp(其中定义了ClassB(;在B.cpp中,我们转发声明ClassA并使用指向它的指针,而不包含a.cpp(定义ClassA的地方(,那么编译器对此完全满意吗?符号解析会正常工作吗?换句话说,这两个对象文件在链接时间之前根本不需要知道彼此吗?

(我假设在visual studio上编译C++代码,而不对默认编译器进行任何更改(

PS:

文件A.cpp

class ClassB;
class ClassA
{
bool JustTakeAClassBPointAndDoNothingWithIt(ClassB* class_b_pointer)
{
if(class_b_pointer)
return true;
else
return false;
return false;
}
}

文件B.cpp

class ClassA;
class ClassB
{
bool JustTakeAClassAPointAndDoNothingWithIt(ClassA* class_a_pointer)
{
if(class_a_pointer)
return true;
else
return false;
return false;
}
}

这个问题太笼统了,无法正确回答,但这是我的2美分。一般来说,只要您只将一个类作为指向它的指针来引用,编译就可以了。例如,这个例子编译得很好:

class B;
int main() {
B * tst;
return 0;
}

然而,一旦您尝试实际实例化指针或访问其任何方法,就需要一个完整的定义。这些示例将无效

class B;
int main() {
B * tst = new B(); // error: allocation of incomplete type 'B'
return 0;
}

或者:

class B;
int main() {
B * tst;
tst->print(); // error: member access into incomplete type 'B'
return 0;
}

tl;博士只要你没有真正与它交互,你就可以使用不完整的类型。如果你使用任何方法或函数,你需要提前声明它们(包括构造函数(

这取决于您到底想对指针做什么——您只能对指向前向声明类型的指针做非常有限的事情。例如,像这样的分配是可以的:

class A;
void myFunc(A* a1)
{
A* a2 = nullptr; 
A* a3 = a1;
}

但您甚至无法递增/递减它们(因为为此,编译器必须知道要"遍历"的对象的大小(。你也不能构造这种类型的对象,也不能访问它的任何方法(因为为此,编译器当然需要知道类型是什么样子,或者它有什么方法(。请参阅XapaJIaMnu在回答中给出的示例。

关于你的问题还有一点——你提到包括";B.cpp";。这表明

  • 只有一个文件同时包含声明和定义,这是不好的做法(将它们拆分为.h和.cpp文件!并且只包含.h文件!(
  • 或者你实际上包括了带有定义的文件,而不是头文件——这是不需要的,除非你做错了什么;例如,模板在这方面可能很棘手——它们基本上也应该在标题中定义

为了提供更多细节,您必须提供更多信息,说明您到底想如何处理此类前向声明的指针。

另请参见

  • C中何时出现不完整类型错误++
  • 我什么时候可以使用远期申报
  • 对于指向不完整类型的指针上的错误算术,我如何知道是什么使不完整类型不完整

最新更新