从.h和.cpp文件定义纯虚函数会产生链接器错误?

3
我试图为我的所有实验工作制定一个“框架”,但是我遇到了一个非常烦人的链接器错误,它涉及到纯虚函数的实现。
当我在.cpp文件中定义纯虚函数(例如returntype classname::function() {.....})时,我会收到一个链接器错误,告诉我未提供纯虚函数的定义...
然而,当我将定义简单地放在头文件中时,它就能正常工作。我知道这听起来很混乱...但下面的代码肯定会帮助您看清发生了什么。
有谁可以帮我理解为什么会发生这种情况吗?
该项目包含4个文件(2个头文件和2个cpp文件)
1> FrameWork.h:
 #ifndef _FRAMEWORK
 #define _FRAMEWORK

 #include<iostream>

 class labTest

 {
   public :
      virtual void execute() = 0;
 };
#endif

======================================

2 >Stack_Array.h :

这是一个名为"Stack_Array.h"的文件。
#include "FrameWork.h"
#include<iostream>
using namespace std;

template <class T>
class Stack_Array : public labTest
  {

       public: 
         virtual void execute();
  };

======================================

3 > Stack_Array.cpp:

这是一个使用数组实现的堆栈代码文件。

#include "Stack_Array.h"
template<class T>

 virtual void Stack_Array<T>::execute(void) // I beleive i am defining the pure virtual function here, but my compiler ll not agree.
  {
      std::cout << "Test";
  }

======================================

4 > Main_Run.cpp :

在 Main_Run.cpp 文件中:
#include<istream>
#include"FrameWork.h"
#include"Stack_Array.h"
#include<vector>
using namespace std;

void main()
  {
   vector<labTest*> list(5);
   vector<labTest*>::iterator it;
   it = list.begin();
   Stack_Array<int>* sa = new Stack_Array<int>();

   list.insert(it,sa);
   list[0]->execute();
   getchar();

  }

构建输出:

1>------ Rebuild All started: Project: Lab FrameWork, Configuration: Debug Win32 ------
1>Build started 11/20/2012 6:16:48 PM.
1>InitializeBuildStatus:
1>  Touching "Debug\Lab FrameWork.unsuccessfulbuild".
1>ClCompile:
1>  Stack_Array.cpp
1>  Main_Run.cpp
1>  Generating Code...
1>Main_Run.obj : error LNK2001: unresolved external symbol "public: virtual void __thiscall Stack_Array<int>::execute(void)" (?execute@?$Stack_Array@H@@UAEXXZ)
1>C:\Users\BSP-4\Documents\Visual Studio 2010\Projects\SFML\Lab FrameWork\Debug\Lab FrameWork.exe : fatal error LNK1120: 1 unresolved externals
1>
1>Build FAILED.
1>
1>Time Elapsed 00:00:01.64

========== Rebuild All: 0 succeeded, 1 failed, 0 skipped =======================

如果我制作我的Stack_Array.h,则它能正常工作:
#include "FrameWork.h"
#include<iostream>
using namespace std;

template <class T>
class Stack_Array : public labTest
{

    public: 
    void execute() // give the definition here instead of Stack_Array.cpp and it will work !
       {
           cout << "Test Success !!";
       }
};

我相信这只是一些愚蠢的小问题。我是否忽略了什么?但我仍需要帮助...

提前感谢...

2个回答

3

模板的定义必须在使用它的所有翻译单元中都可用(除非涉及显式的特化/实例化,这里不是这种情况)。换句话说,类模板的成员函数必须在头文件中定义。


2

void Stack_Array<T>::execute(void)只在其定义的编译单元中定义。在Stack_Array.cpp之外,编译器不知道如何在Stack_Array<T>上实现execute。通常情况下,模板实例化请求不会从一个执行单元传递到另一个执行单元。现在,您可以通过将Stack_Array<T>的实现放入头文件中或在Stack_Array.cpp中明确实例化要导出的<T>来解决此问题。

C ++尝试添加跨编译单元导出和请求模板实例化的支持,但这很棘手。

最简单的解决方案是将实现移到头文件中,并确保方法是内联的(或在类体中)。


谢谢你的解释。C++ 的这种行为对我来说有点出乎意料。我在论坛或其他地方没有看到很多人讨论这个问题...不管怎样,还是谢谢。我会把我的代码放到头文件中... - Jithin Peter

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接