前置声明是否完全消除指针类型的任何#include依赖?

3
假设我们有一个源文件A.cpp,在其中前向声明了类型ClassB,并且在没有包含定义ClassB的文件B.cpp的情况下一直使用指向ClassB的指针;在B.cpp中,我们前向声明了ClassA并使用了指向它的指针,而没有包含定义ClassA的A.cpp文件。那么编译器是否能完全接受这种情况?符号解析是否能正常工作?换句话说,这两个目标文件在链接之前不需要互相知道对方的存在吗?
(我假设在Visual Studio上编译C++代码,而没有对默认编译器进行任何更改)
附注:
文件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;
}
}

1
这个问题太模糊和笼统,无法给出权威的答案。C++是当今使用最复杂的通用编程语言。唯一回答“这会起作用吗”,当你不知道时,就是去尝试它。顺便说一句,除了编译器错误的情况外,你的编译器是否“没有更改默认编译器的Visual Studio”是完全无关紧要的。 C++就是C++。 - Sam Varshavchik
“然后我们继续使用指向ClassB的指针”是指您只是在传递指针并对其进行通用指针操作;还是说,您是通过该指针访问与ClassB特定相关的内容?如果是后者,那么只有在包含B的定义文件时才能起作用(我想)。 - codeling
@codeling 是的,确切地说,只有指针的一般操作。 - Physician
1
如果没有明确的代码示例,我认为你只使用前向声明就可以了。但是很难确定。 - codeling
1
非常相关:https://dev59.com/LlcP5IYBdhLWcg3wAmKy。不可否认,我不理解为什么答案中说很难判断。实际上,这很简单:前向声明类型是不完整的,你不能做任何需要完整类型的事情,就这样。 - 463035818_is_not_a_number
显示剩余4条评论
2个回答

2

这取决于你想使用指针做什么 - 对于前向声明类型的指针,你只能进行非常有限的操作。例如,像这样的赋值是可以的:

class A;

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

但是你甚至不能对它们进行递增/递减操作(因为编译器必须知道对象的大小才能“遍历”)。你也无法构造这种类型的对象或访问其任何方法(因为当然编译器需要知道类型的样子或其具有哪些方法)。请参见XapaJIaMnu的答案中给出的示例
关于你的问题还有一个额外的要点-你提到了包含“B.cpp”。这表明:
  • 你只有一个文件包含了声明和定义,这是不好的做法(将它们分成.h和.cpp文件!并且只包含.h文件!)。
  • 或者你实际上包含了定义文件而不是头文件-除非你做错了什么,否则从不需要这样做;例如,模板在这方面可能会很棘手-它们基本上也应该在头文件中定义。
为了提供更多细节,你需要提供关于你想用这种前向声明指针做什么的更多信息。
另请参阅:

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;
}

简而言之,只要不与之交互,就可以使用不完整类型。如果使用任何方法或函数,则需要提前声明它们(包括构造函数)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接