代码改变世界

c++模板类成员的声明和定义

2016-05-09 16:39  zmkeil  阅读(5590)  评论(0编辑  收藏  举报

c++模板类成员的声明和定义应该都放在*.h中,有普通类不一样。

如果定义放在*.cpp中,最终链接时,会报方法undefined错误。

参考:http://users.cis.fiu.edu/~weiss/Deltoid/vcstl/templates

 

如果非要定义在*.cpp中,一定要具体化模板类型,如下,但这样意味着你要定义无数个。

所以还是放在*.h中吧,用到的地方,编译器会帮你定义具体类型的方法。

// error
template<typename T>
A<T>::func() {
    // ...
}

// OK
template<>
A<int>::func() {
    // ...
}

  

一个例子:

// template.h

#include <iostream>
#ifndef  __TEMPLATE_H_
#define  __TEMPLATE_H_

class ContextAbstr {
public:
    virtual void log() = 0;
};

template<typename T>
class Sam {
public:
    Sam() {}
    virtual ~Sam() {}

    void func() {
        _context.log();
        return;
    }

public:
    static int snumber;
    static void sfunc();

private:
    T _context;
};

// template class's method must be define in *.h
// so when be called, different T expand to different definetion
// otherwise, ld cann't find the method
template<typename T>
void Sam<T>::sfunc() {
    std::cout << "hello template static func" << std::endl;
}

// regular class's method be declared in *.h, and defined in *.cpp
// otherwise, result to mutli-definetion error
class Context : public ContextAbstr {
public:
    void log();
};

#endif  //__TEMPLATE_H_

// template.cpp

#include "template.h"

// template class's member also can be defined in *.cpp, but must specilize the T
template<>
int Sam<int>::snumber = 10;

template<>
int Sam<float>::snumber = 15;

// regular class's method be defined in *.cpp, avoid mutli-definetion
void Context::log() {
    std::cout << "hello world from template class" << std::endl;
}

// test_template.cpp

#include "template.h"

int main()
{
    Sam<Context>::sfunc();

    Sam<Context>* sam = new Sam<Context>();
    sam->func();

    Sam<int>* sam_int = new Sam<int>();
    std::cout << "int's snumber: " << sam_int->snumber << std::endl;

    Sam<float>* sam_float = new Sam<float>();
    std::cout << "float's snumber: " << sam_float->snumber << std::endl;

    return 0;
}