【问题标题】:Does forward declaration fully remove the need for any #including for pointer types?前向声明是否完全消除了对指针类型的任何#include 的需要?
【发布时间】:2022-01-19 12:32:03
【问题描述】:

假设我们有一个源文件 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;
}
}

【问题讨论】:

  • 这太模糊笼统,无法给出权威答案。 C++ 是当今使用的最复杂的通用编程语言。当您不知道时,回答“这行得通”的唯一方法是尝试一下。附言除非出现编译器错误,否则您的编译器是否是“没有对默认编译器进行任何更改的 Visual Studio”,完全无关紧要。 C++ 就是 C++。
  • “那么我们继续使用指向 ClassB 的指针”是否意味着您只是传递指针并在其上执行通用指针操作;还是您的意思是,通过该指针访问特定于 ClassB 的任何内容?后者仅在您包含 B 的定义文件时才有效(我认为)
  • @SamVarshavchik 你确定你仔细阅读了吗?我不同意你的描述。尽管如此,感谢您的宝贵时间。
  • 那么我看不出你为什么不应该只使用前向声明。但是如果没有明确的代码示例就很难说 ;)
  • 非常相关:stackoverflow.com/questions/44963201/…。诚然,我不明白为什么答案说很难说。其实很简单:前向声明的类型是不完整的,你不能做任何需要完整类型的事情,就是这样

标签: c++ linker include forward-declaration link-time-optimization


【解决方案1】:

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

【讨论】:

    【解决方案2】:

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

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

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

    关于您的问题还有一点 - 您提到包括“B.cpp”。这表明要么

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

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

    另见

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-12-01
      • 2015-03-10
      • 2017-09-16
      • 2020-04-03
      • 2011-07-09
      相关资源
      最近更新 更多