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

Defining pure virtual functions from .h and .cpp files yields linker error?

本文关键字:链接 错误 函数 cpp 文件定义 虚拟      更新时间:2023-10-16

我试图为我所有的实验室工作构建一个"框架",但后来我在处理纯虚拟函数的实现时遇到了一个令人沮丧的链接器错误。。

当我从.cpp文件中定义纯虚拟函数时(如returntype类名::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:

#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:

#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 "DebugLab 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:UsersBSP-4DocumentsVisual Studio 2010ProjectsSFMLLab FrameWorkDebugLab 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 !!";
}
};

我确信这是件愚蠢的事。。我是不是忽略了什么?。。但我仍然需要帮助。。。。

提前感谢。。。

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

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

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

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