3

假设我们有一个源文件 A.cpp,我们在其中转发声明了一个类型 ClassB,然后我们继续使用指向 ClassB 的指针,而没有 #include 文件 B.cpp(其中定义了 ClassB);在 B.cpp 中,我们转发声明 ClassA 并使用指向它的指针,而无需 #include 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;
}
}
4

2 回答 2

2

这个问题真的太笼统了,无法正确回答,但这是我的 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;博士; 只要您不实际与之交互,您就可以使用不完整的类型。如果使用任何方法或函数,都需要提前声明(包括构造函数)

于 2021-12-16T12:17:35.753 回答
2

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

class A;

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

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

关于您的问题的另一点-您提到包括“B.cpp”。这表明无论是

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

为了提供更多详细信息,您必须提供更多信息,说明您想要使用这些前向声明的指针做什么。

也可以看看

于 2021-12-16T12:10:40.247 回答