开发者

Common Practice for Template Function Defination - Mix with Function Declaration?

开发者 https://www.devze.com 2022-12-12 08:30 出处:网络
Most of the time, I \"avoid\" to have the following style in my single header file. class a { void fun();

Most of the time, I "avoid" to have the following style in my single header file.

class a {
    void fun();
};

void a::fun() {
}

In order to avoid the following error. I try to separate class definition in cpp file and class declaration in h file. For example, the below is the wrong example :


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();
}

I will get the following error :

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

However, when come to template, I will usually do it this way :

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

May I know it this a good practice?

Thanks.

Cheok


You can eliminate the LNK2005 error by declaring the definition of a::fun() as inline. For example:

// a.h

// ...

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

With templates, the problem doesn't occur because the compiler/linker take care of ensuring that there is only one definition of each template instantiation.

If, for some reason, you don't want the function to be inline, then you'll have to ensure that it only gets compiled once. For example, something like this:

// a.h

// ...

#ifdef DEFINE_CLASS_A_FUNCTIONS

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

#endif

and then, somewhere, you'll need to do something like this (exactly once):

#define DEFINE_CLASS_A_FUNCTIONS
#include "a.h"


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

You are getting this error because a::fun() is not inline

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

Also, refer C++ FAQ : How can I avoid linker errors with my template functions?

0

精彩评论

暂无评论...
验证码 换一张
取 消