模板函数定义的通用实践 - 与函数声明混合使用?

时间:2009-11-26 07:59:28

标签: c++

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

class a {
    void fun();
};

void a::fun() {
}

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


的main.cpp

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

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

A.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

然而,当来到模板时,我通常会这样做:

A.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

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

感谢。

2 个答案:

答案 0 :(得分:2)

您可以通过将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"

答案 1 :(得分:1)

  

1&gt; b.obj:错误LNK2005:“public:   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 ++ FAQ:How can I avoid linker errors with my template functions?