【问题标题】:c++: class declaration and definition separated inside header causes Duplicate Symbolc ++:在标头内分隔的类声明和定义导致重复符号
【发布时间】:2011-11-26 22:16:52
【问题描述】:

如果我的类是模板类,我通常只会在头文件中包含类的定义。- 如果是这种情况,我仍然喜欢像这样在头文件中拆分声明和定义:

template<class T>
class Foo
{
public:

    Foo();

    void fooFunc();
};


template<class T>
Foo<T>::Foo()
{

}

template<class T>
void Foo<T>::fooFunc()
{

}

该代码也可以编译。但如果我删除模板:

class Foo
{
public:

    Foo();

    void fooFunc();
};


Foo::Foo()
{

}

void Foo::fooFunc()
{

}

我收到 Foos 函数的重复符号错误。我非常确定这应该有效,但我很惊讶它没有。这是预期的行为吗?如果我在定义之前添加内联,它也可以工作。

【问题讨论】:

    标签: c++


    【解决方案1】:

    是的,这是预期的行为。

    内联函数旨在单独编译到每个调用站点中,因此重复是没有问题的。对于模板函数,编译器在目标文件中标记它们,这样链接器基本上会忽略重复项,因为很难预测模板将在哪里实例化或不会在哪里实例化。

    但是传统的函数预计只定义一次。如果您在头文件中定义一个,它将被编译到包含头文件的每个翻译单元中,如果您有多个包含函数副本的目标文件,则会在链接时导致“重复符号”错误。

    【讨论】:

    • 好的,谢谢,我通常从不使用非模板类执行此操作,只是偶然发现了这一点。- 我很惊讶它没有用,但你的解释很有道理!
    • 您可能想了解one-definition rule 和“COMDAT 部分”,它们是用于合并模板实例化的重复定义和内联函数的外联副本的机制。
    【解决方案2】:

    我猜链接器知道在多个翻译单元中定义的类和在多个翻译单元中定义的模板类之间的区别。对于前者,它会产生重复符号错误,对于后者,它将两个实例视为同一事物,并且只使用其中一个。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-01-28
      • 1970-01-01
      • 2018-01-31
      • 1970-01-01
      • 1970-01-01
      • 2020-09-11
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多