-1

我在一个名为的类中定义了一个公共模板函数EventDispatcher

public:
    template <class className> void AddEventListener ( className* );

该函数实现如下:

template <class className>
void EventDispatcher::AddEventListener ( className* ptr )
{

};

然后在某个班级中,我创建了Timer一个孩子的实例EventDispatcher并调用AddEventListener

timer->AddEventListener ( this );

在我得到一个错误之后

/tmp/ccjRF7sK.o: In function `AirHockeyServer::AirHockeyServer()':
AirHockeyServer.cpp:(.text+0xa5): undefined reference to `void EventDispatcher::AddEventListener<AirHockeyServer>(AirHockeyServer*)'
/tmp/ccjRF7sK.o: In function `AirHockeyServer::AirHockeyServer()':
AirHockeyServer.cpp:(.text+0x187): undefined reference to `void EventDispatcher::AddEventListener<AirHockeyServer>(AirHockeyServer*)'
collect2: ld returned 1 exit status
4

6 回答 6

4

你说你已经定义了函数,但你只向我们展示了一个声明。您还需要一个定义:

template <class className> void AirHockeyServer::AddEventListener ( className* )
{
    // code goes here
}

注意这个问题现在已经更新,表明某处有一个定义。

因为它是一个模板,所以它需要放在一个标题中,包含在每个使用该函数的源文件中。模板在使用时被实例化,并且需要它们的完整定义来实例化它们。

等效地,您可以在类定义中定义它:

public:
    template <class className> void AddEventListener ( className* )
    {
        // code goes here
    }
于 2012-08-27T11:00:31.670 回答
1

这是一个链接器错误,告诉您链接器看不到AddEventListener成员函数的实现。对于模板,通常将函数的实现放在头文件中,因此可以为任何模板参数参数实例化它们。

于 2012-08-27T10:58:36.833 回答
1

链接器找不到template<class className> AddEventListener<className*>. 对于模板,实现必须与声明在同一个文件中。

于 2012-08-27T11:00:36.650 回答
1

当您有模板时,您不能真正将类拆分为单独的头文件和源文件。您还需要将定义放在头文件中。

于 2012-08-27T11:02:24.340 回答
1

模板函数需要针对特定​​类型进行实例化。将实现放在 .cpp 文件中不会这样做。

最简单的方法是将它放在类定义本身中,或者放在头文件中。

另一种方法是将其保存在 .cpp 文件中,然后为您需要的类型进行显式实例化:

template void EventDispatcher::AddEventListener(AirHockeyServer*);
于 2012-08-27T11:03:29.987 回答
0

(这个问题是“未定义的引用”模板类构造函数的副本)并且那里的答案已经足够了。

总结一下,有两种方法可以解决这个问题:

  • 正如@LuboAntonov 所说,您可以放在template void EventDispatcher::AddEventListener(AirHockeyServer*);函数模板的定义之后。
  • 如许多其他人所述,将实现移动到标题中。

有关完整详细信息,请参阅另一个问题。

于 2012-08-27T11:40:19.447 回答