c++ - 未编译函数模板中使用的类的前向声明

标签 c++ templates gcc forward-declaration

我有以下代码,它不是用 gcc 编译的,但是用 MSVC 编译得很好。

class B;

class A
{
    B *_parent;

public:

    template <typename T>
    void Do(T val)
    {
        _parent->DoB(val);
    }

    A(B *parent)
        :   _parent(parent)
    {
    }
};

class B : public A
{
public:

    B()
        : A(nullptr)
    {
    }

    void DoB(int val)
    {
        cout << val << endl;
    }
};

int main() {
    B b;
    A a(&b);
    a.Do(10);
    return 0;
}

编译错误如下:

prog.cpp: In member function ‘void A::Do(T)’:
prog.cpp:15:10: error: invalid use of incomplete type ‘class B’
   _parent->DoB(val);
          ^~
prog.cpp:4:7: note: forward declaration of ‘class B’
 class B;
       ^

根据类似的帖子,由于标准的第 14.6.9 段,gcc 的行为是正确的。但这是违反直觉的,因为模板应该只在使用的地方实例化。并且唯一的用法发生在所有类都被定义之后。

我的问题是这个问题的解决方法是什么?因为在这种情况下使用成员模板真的很方便。也许问题出在体系结构或其他方面?

最佳答案

您可以声明A 中依赖于B 的部分是已知的,但稍后定义它们。声明看起来像这样

class B;

class A
{
    B *_parent;

    public:
        template <typename T> void Do(T val); /* (see below) */
        A(B *parent) :   _parent(parent) {}
};

然后是B的定义

class B : public A { /* As before. */ };

最后定义缺失的部分

template <typename T> void A::Do(T val)
{
    _parent->DoB(val); /* Fine, B is known. */
}

作为旁注,使用 gcc 8 编译的原始代码仅带有警告。

关于c++ - 未编译函数模板中使用的类的前向声明,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51476511/

相关文章:

c++ - 无法在 VS 对话框编辑器中更改组合框的高度

C++ 加减 100 位数字

c++ - 如何在模板化转换运算符中消除这种构造的歧义?

C++:复制构造函数正在删除原始对象中的节点

使用头文件编译

linux - 我可以运行从更高版本的 gcc 编译的二进制文件吗?

具有不同参数的派生类中的 C++ 方法

c++ - 为什么我的 std::vector.push_back 抛出 bad_alloc 异常

用于连接 std::vector 和 std::array 类型的 C++ 模板函数

c - 如果我有一个在标签后初始化的变量,为什么我会得到 "a label can only be part of a statement and a declaration is not a statement"?