C++ 抽象类模板 + 特定类型的子类 = 链接器有问题
Posted
技术标签:
【中文标题】C++ 抽象类模板 + 特定类型的子类 = 链接器有问题【英文标题】:C++ abstract class template + type-specific subclass = trouble with linker 【发布时间】:2010-05-05 10:18:52 【问题描述】:有问题的项目是关于相互通信的不同端点。端点发送事件(超出当前问题的范围)并且可以处理传入事件。每个事件在一个通用对象中表示如下:
#pragma interface
... // some includes
template<typename T>
class Event
public:
Event(int senderId, Type type, T payload); // Type is an enum
Event(int senderId, Type type, int priority, T payload);
virtual ~Event();
virtual int getSenderId();
virtual int getPriority();
virtual T getPayload();
void setPriority(const int priority);
protected:
const int senderId;
const Type type;
const T payload;
int priority;
;
它的实现类带有#pragma implementation 标签。
端点定义如下:
#pragma interface
#include "Event.h"
template<typename T>
class AbstractEndPoint
public:
AbstractEndPoint(int id);
virtual ~AbstractEndPoint();
virtual int getId();
virtual void processEvent(Event<T> event) = 0;
protected:
const int id;
;
它也有自己的实现类,但只定义了构造函数、析构函数和getId()。
这个想法是为每种不同的有效负载类型创建具体的端点。因此,我对每种类型都有不同的有效负载对象和特定的事件类,例如
Event<TelegramFormatA>, Event<TelegramFormatB>
和
ConcreteEndPoint for TelegramFormatA,
ConcreteEndPoint for TelegramFormatB
分别。后面的类被定义为
class ConcreteEndPoint : AbstractEndPoint<TelegramFormatA>
...
我正在使用 g++ 4.4.3 和 ld 2.19。一切都编译得很好,但是链接器抱怨未定义对特定类型事件类的引用,例如
Event<TelegramFormatA>::Event(....) .
我尝试使用显式实例化
template class AbstractEndPoint<TelegramFormatA>;
但无法克服上述链接器错误。
任何想法都将不胜感激。
【问题讨论】:
【参考方案1】:类模板的函数模板和成员函数必须在头文件中实现,而不是 .cpp 文件。我想您在 .cpp 文件中实现了Event<T>::Event()
?
【讨论】:
【参考方案2】:正如 sbi 已经指出的那样,不允许在源文件和头文件中分离模板的接口和实现。查看此链接了解详情(页尾)http://www.cplusplus.com/doc/tutorial/templates/
【讨论】:
允许在 .cpp 文件中包含实现,但必须在头文件中#included 以便实现可见。它也不能自己编译。当它以这种方式组织时,通常会使用不同的文件扩展名(通常是 .inc)。【参考方案3】:我刚刚找到了解决方案。信不信由你,它与 GNU 链接器 (ld) 的 v2.20 完美链接,但无法与 ld 2.19 链接。
顺便说一句
#pragma interface
和
#pragma implementation
是一种特定于 g++ 的解决方法,用于解决在头文件中实现模板类的问题。使用编译指示标签可以避免它,所以这不是问题,但无论如何感谢您的建议。
【讨论】:
以上是关于C++ 抽象类模板 + 特定类型的子类 = 链接器有问题的主要内容,如果未能解决你的问题,请参考以下文章