【问题标题】:Common Practice for Template Function Defination - Mix with Function Declaration?模板函数定义的常见做法 - 与函数声明混合?
【发布时间】:2009-11-26 07:59:27
【问题描述】:

大多数时候,我“避免”在我的单个头文件中使用以下样式。

class a {
    void fun();
};

void a::fun() {
}

为了避免下面的错误。我尝试将 cpp 文件中的类定义和 h 文件中的类声明分开。例如,下面是错误的例子:


main.cpp

#include "b.h"
#include "a.h"

int main()
{
    a aa;
    b bb;
}

啊.h

#ifndef A_H
#define A_H

#include <iostream>

class a {
public:
    virtual int fun();
};


int a::fun()
{
    int t;
    std::cout << "a" << std::endl;
    return t;
}

#endif

b.h

#ifndef B_H
#define B_H

#include <iostream>
#include "a.h"

class b {
public:
    b();
};

#endif

b.cpp

#include "b.h"
#include "a.h"

b::b()
{
    a aa;
    aa.fun();
}

我会得到以下错误:

1>b.obj : error LNK2005: "public: virtual int __thiscall a::fun(void)" (?fun@a@@UAEHXZ) already defined in main.obj

但是,当谈到模板时,我通常会这样做:

啊.h

#ifndef A_H
#define A_H

#include <iostream>

template <typename T>
class a {
public:
    virtual T fun();
};


template<typename T> T a<T>::fun()
{
    T t;
    std::cout << "a" << std::endl;
    return t;
}

#endif

我可以知道这是一个好习惯吗?

谢谢。

【问题讨论】:

    标签: c++


    【解决方案1】:

    您可以通过将a::fun() 的定义声明为inline 来消除LNK2005 错误。例如:

    // a.h
    
    // ...
    
    inline int a::fun()
    {
        int t;
        std::cout << "a" << std::endl;
        return t;
    }
    

    使用模板不会出现问题,因为编译器/链接器会确保每个模板实例化只有一个定义。

    如果出于某种原因,您不希望函数为inline,那么您必须确保它只编译一次。例如,像这样:

    // a.h
    
    // ...
    
    #ifdef DEFINE_CLASS_A_FUNCTIONS
    
    int a::fun()
    {
        int t;
        std::cout << "a" << std::endl;
        return t;
    }
    
    #endif
    

    然后,在某个地方,你需要做这样的事情(恰好一次):

    #define DEFINE_CLASS_A_FUNCTIONS
    #include "a.h"
    

    【讨论】:

    • 将虚函数声明为内联似乎不正确。
    • @Naveen 为什么不呢?如果可以,编译器可以并且将内联函数,否则他将忽略内联。如果它被声明为内联,他将处理一个定义规则。
    • 我有点困惑..更有效的 C++ (Scott Mayers) 第 24 条说,如果类中的所有虚方法都是内联的,则可能会出现问题。在这种情况下,可以在包含此类的所有目标文件中生成该类的 v-table
    • 我不打算内联函数。
    【解决方案2】:

    1>b.obj:错误 LNK2005:“公共: virtual int __thiscall a::fun(void)" (?fun@a@@UAEHXZ) 已经定义在 main.obj

    您收到此错误是因为 a::fun() 不是 inline

    inline int a::fun()
    {
        int t;
        std::cout << "a" << std::endl;
        return t;
    }
    

    另外,请参阅 C++ 常见问题解答:How can I avoid linker errors with my template functions?

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-10-07
      • 2016-05-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-11-19
      相关资源
      最近更新 更多