模板函数原型声明和定义实现必须放在一起

问题起因是我在一个.h文件中定义模版类,忘了在.cpp中定义函数时如何写(就是忘了 CLASS<T>::show中的<T>),然后顺便在.h中声明了个模板函数(函数原型),又在cpp中定义,结果在主函数中用时,出现错误(未定义)。于是搜索,原来总结一句话如下

模版函数在.h中必须定义声明一块,都在其中。不能像普通函数一样,一个.h一个cpp,同样模板类的函数也不行,只是它可以在类中先声明,然后在类外定义,但也必须在一个.h中

这里我又想到一个问题,那么如果摸板类,如何封装,只留接口而保密实现呢。
至于原因stackoverflow上有解释,在最末尾也贴了,其实我觉得就是模版函数和普通函数不一样, The compiler needs to have access to the entire template definition (not just the signature) in order to generate code for each instantiation of the template, so you need to move the definitions of the functions to your header.

.h

#ifndef QUEUE_H

#define QUEUE_H

#include<iostream>

template<class T>

class FQueue

{

private:

 

    T fq[10];

public:

 

 \

    FQueue(int qs ); //给参数提供默认值

    ~FQueue();

    bool isempty() const;

    bool isfull() const;

    int queuecount() const;

    bool inqueue(const T &item);

    bool dequeue(const T &item);

 

};

 

void show();  //普通函数这样是没有问题的

 

//下面这个是原型在这h.定义在cpp

template<class T> void shimobanhwai(T a);

 

//下面这样是对的,都放在.h文件中

template<class T> void shimobanhnei(T a)

{

     std::cout << "a is " << a << std::endl;

}

#endif // QUEUE_H

 

 

.cpp

#include"queue.h"

#include<iostream>

using namespace std;

template<class T>

FQueue<T>::FQueue(int qs)   //这样也不行,必须放在.h中,否则当建立对象时还是会出现未定义

{

    T* fqp = new T[qs];

 

}

template<class T>

FQueue<T>::~FQueue()    //class名字后面别忘了加<T>,这是我经常忘的

{}

template<class T>

bool FQueue<T>::isempty() const

{}

template<class T>

bool FQueue<T>::isfull() const

{}

template<class T>

int FQueue<T>::queuecount() const

{}

template<class T>

bool FQueue<T>::inqueue(const T &item)

{}

template<class T>

bool FQueue<T>::dequeue(const T &item)

{}

 

void show()

{

    cout << "Am i right?" << endl;

}

template<class T>

void  shimobanhwai(T a)

{

    cout << "a is " << a << endl;

}

 

 

Main.cpp

#include <iostream>

#include"queue.h"

 

 

using namespace std;

//模板函数、模板类

//新发现,模板不能分.h.cpp

 

int main()

{

 

    shimobanhnei(5);

    //shimobanhwai(5);//出错

    show();

   // why(3);

    cout << " bye!" << endl;

    cin.clear();  //清楚标志位

    while (cin.get() != '\n')

        continue;            //清楚输入流数据

 

    return 0;

}

 


stackoverflow上我觉得比较经典的解释

Q:

Why can templates only be implemented in the header file?

A:

Because when instantiating a template, the compiler creates a new class with the given template argument. For example:

template<typename T>
struct Foo
{
    T bar;
    void doSomething(T param) {/* do stuff using T */}
};

// somewhere in a .cpp
Foo<int> f; 

When reading this line, the compiler will create a new class (let's call it FooInt), which is equivalent to the following:

struct FooInt
{
    int bar;
    void doSomething(int param) {/* do stuff using int */}
}

Consequently, the compiler needs to have access to the implementation of the methods, to instantiate them with the template argument (in this case int). If these implementations were not in the header, they wouldn't be accessible, and therefore the compiler wouldn't be able to instantiate the template.

A common solution to this is to write the template declaration in a header file, then implement the class in an implementation file (for example .tpp), and include this implementation file at the end of the header.

// Foo.h
template <typename T>
struct Foo
{
    void doSomething(T param);
};

#include "Foo.tpp"

// Foo.tpp
template <typename T>
void Foo<T>::doSomething(T param)
{
    //implementation
}

This way, implementation is still separated from declaration, but is accessible to the compiler.

Another solution is to keep the implementation separated, and explicitly instantiate all the template instances you'll need:

// Foo.h

// no implementation
template <typename T> struct Foo { ... };

//----------------------------------------    
// Foo.cpp
// implementation of Foo's methods

// explicit instantiations
template class Foo<int>;
template class Foo<float>;
// You will only be able to use Foo with int or float

If my explanation isn't clear enough, you can have a look at the C++ FaqLite on this subject.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值