【发布时间】:2014-06-19 22:52:43
【问题描述】:
这是我认为我理解 C++ 虚方法相当好的情况之一,然后出现了一个例子,我意识到,遗憾的是,我没有。有没有读过这篇文章的人可以理解以下内容?
这是一些测试代码,我在其中定义了一个非常简单的基类(实际上只是一个双元素结构),一个包含虚拟 void 方法的抽象模板类,然后是一个从它们两者显式继承的派生类用具体方法覆盖虚拟 void 方法。
#include <string.h> // For memcpy
#include <vector> // For std::vector
struct int_array_C
{
int n;
int* contents;
};
template <typename T> class array_template
{
public:
array_template<T>() {}
array_template<T>(const array_template<T> &source)
{
*p_n = *(source.p_n);
setPointers(&(source.local_contents[0]));
}
// ..and in reality, a bunch of other array manipulation functions
protected:
virtual void setPointers(const T* data) = 0;
int *p_n;
std::vector<T> local_contents;
};
class int_array : public int_array_C, public array_template<int>
{
public:
int_array() : array_template<int>()
{
n = 0; contents = NULL;
}
protected:
virtual void setPointers(const int* data)
{
p_n = &n;
local_contents.resize(n);
memcpy(static_cast<void *>(&local_contents[0]),
static_cast<const void *>(data), n*sizeof(int));
contents = &local_contents[0];
}
};
int main()
{
int_array myArray;
int_array yourArray(myArray);
return 1;
}
在 main() 的第二行调用复制构造函数时,参数是派生类的实例,该类具有具体的 setPointers() 方法。因此,当调用模板类的复制构造函数并遇到对 setPointers() 的调用时,我希望多态性规则开始生效并调用 派生 类的 setPointers() 方法。
事实上,编译器对此感到窒息;在编译时我收到警告说
"Warning: call of pure virtual function at line 18"
在链接时链接器失败并显示一条消息
error LNK2019: unresolved external symbol "protected: virtual void __cdecl array_template<int>::setPointers(int const *)" (?setPointers@?$array_template@H@@MEAAXPEBH@Z) referenced in function "public: __cdecl array_template<int>::array_template<int>(class array_template<int> const &)" (??0?$array_template@H@@QEAA@AEBV0@@Z)
在 Windows 上使用 Visual C++ 和 Intel C++ 以及在 Linux 上使用 gcc 会发生完全相同的事情(错误消息的文本略有不同),因此这显然是对语言规则的真正违反,而不仅仅是编译器的怪癖。但我看不出问题出在哪里。
那么,我做错了什么,我怎样才能使这项工作按预期进行?
【问题讨论】:
-
代码有很多错误,伙计。
-
你不能从基类构造函数中调用派生类的虚函数,因为在调用它的时候派生类还没有被构造出来。
-
调用是错误的,但我仍然不明白为什么这最终是链接错误而不是运行时 UB
-
我不同意这是引用答案的重复的断言。确实有很多事情会在链接时导致未定义的引用错误,但我在列出的那些中找不到这个。正如下面所讨论的(并由@Paul Griffiths 指出),这个问题的关键是基类方法和派生类方法的实例化顺序,我在引用的答案中找不到任何相关信息。 Cheers 和 hth 引用的常见问题解答。 Alf 的相关性更高,但如果没有 Paul Griffiths 的评论,我想我什至不会在那里找到答案。
标签: c++ templates inheritance virtual overriding