【问题标题】:C++ - undefined reference to Base class operatorC++ - 对基类运算符的未定义引用
【发布时间】:2015-12-08 16:06:05
【问题描述】:

我有一个模板基类 Vect,VectDynamic 派生自它。

基类(Vect.h):

template <typename Elem>
class Vect
{
public:
    virtual Elem& operator[](std::ptrdiff_t);
};

派生类(VectDynamic.h):

#include "Vect.h"

template <typename Elem>
class VectDynamic: public Vect<Elem>
{
    std::size_t _dim;
    Elem* _val;
public:
    explicit VectDynamic(std::size_t dim = 0): _dim(dim), _val(new Elem[dim]) {}
    VectDynamic(std::size_t, const Elem&);
    VectDynamic(const VectDynamic&); 
    Elem& operator[](std::ptrdiff_t) override;
};

template <typename Elem>
VectDynamic<Elem>::VectDynamic(std::size_t size, const Elem& e):
    _dim(size), _val(new Elem[size]) 
{
    for (std::size_t i = 0; i < size; ++i) _val[i] = e;
}

template <typename Elem>
VectDynamic<Elem>::VectDynamic(const VectDynamic& v): 
    _dim(v._dim), _val(new Elem[v._dim])
{
    for (std::size_t i = 0; i < v._dim; ++i) _val[i] = v._val[i];
}

template <typename Elem>
Elem& VectDynamic<Elem>::operator[] (std::ptrdiff_t i) 
{
    if (std::size_t(i) >= _dim)
        throw std::out_of_range("VectDynamic : Index out of range");
    return _val[i];
}

当我尝试像这样 (main.cpp) 创建派生类的实例时:

#include "VectDynamic.h"

int main()
{
    VectDynamic<double> v1(5, 2);

    return 0;
}

我最终在两个类中都遇到了这个错误:
undefined reference to 'VectDynamic&lt;double&gt;::operator[](long)'

现在我知道很多帖子都在谈论这种错误,但经过数小时的搜索,我找不到任何原因导致我的情况发生这种错误。
我认为错误不会来自我包含文件的方式,因为当所有内容都在一个文件中时它也不起作用。

我在this 的帖子中读到,这可能是由于基类的隐式实例化在声明派生类时进行的,因为尚未定义基类的方法。

您认为这是问题所在吗? 什么是体面的解决方法?

编辑:忘记添加孩子的operator[],现在添加(它没有导致任何错误,因为它在我的代码中)。

【问题讨论】:

  • 为什么基类运算符声明中没有=0(因为您似乎不想定义它)?
  • 制作Vectoperator[]纯虚拟?
  • 谢谢你们,解决了,虽然我不明白为什么问题没有早点出现......

标签: c++ templates inheritance operator-overloading


【解决方案1】:

尽管Vect&lt;double&gt;::operator[] 永远不会被调用,但在派生对象的构造过程中必须暂时使用基础vtable,并且当您声明事物时,基础vtable 有一个指向该未定义方法的指针。这应该通过在基方法的声明中添加“=0”(通常描述为“纯虚拟”)来解决。

改成

template <typename Elem>
class Vect
{
public:
    virtual Elem& operator[](std::ptrdiff_t)=0;
};

【讨论】:

  • 我将您的评论放在答案中,这样我就可以问心无愧地投票了。
  • 您能否详细说明使基类成为纯类将​​如何改变孩子operator[] 的定义?
  • @MarkB 您是否注意到 Bathsheba 从我之前的评论中有用地复制到我的答案中的解释?使该基本函数成为纯函数确实会更改派生函数,它会更改基本 vtable。派生构造函数使用基构造函数,后者使用基 vtable。原始错误来自基本 vtable。基本 vtable 的使用没有任何作用,并且可以被优化器删除。但是根据它的删除是不正确的。
  • @JSF 我已经阅读了大约五次错误消息,据我所知,它说未定义对VectDynamic&lt;double&gt;::operator[](long) 的引用,换句话说就是子运算符函数体本身。这与可能还存在的任何 vtable 关注点是正交的。
  • @MarkB,对不起,你是对的。我看到了一个错误,但错过了更大的错误。
【解决方案2】:

从错误中可以清楚地看出您只是没有定义VectDynamic&lt;double&gt;::operator[]。如果您不想要 [] 运算符,只需删除函数声明。如果你确实想要它,你需要实现它。

请注意,由于它是一个模板类,因此您不能在非头源文件中实现该运算符。

既然我已经说了这么多,我还要指出,因为你没有(正确地)遵循 0、3 或 5 的规则,你会泄漏内存;你不使用std::vector有什么原因吗?

【讨论】:

  • 我在这段代码中没有遵循三/五/零的规则,因为我只复制了导致我的问题的部分。我不使用std::vector 没有什么特别的原因,只是我使用的东西对我来说很好用,所以我觉得没有必要寻找其他东西
猜你喜欢
  • 2012-06-24
  • 1970-01-01
  • 1970-01-01
  • 2020-09-15
  • 2018-09-17
  • 1970-01-01
  • 2016-01-16
  • 2021-06-11
  • 2019-04-29
相关资源
最近更新 更多