【问题标题】:Undefined reference to `vtable' in the constructor [duplicate]构造函数中对“vtable”的未定义引用[重复]
【发布时间】:2017-04-14 01:38:04
【问题描述】:

我尝试学习 C++ 构造函数,Imma noobie 还没有。我写了下一节课:
screen.h

#ifndef SCREEN_H
#define SCREEN_H

#include "pch.h"

class Screen
{
public:
    Screen(const std::string& name);
    Screen(const Screen& screen);
    Screen(Screen&& screen);

    const std::string& name() const;

    virtual void draw();
private:
    std::string m_name;
};

#endif // SCREEN_H

screen.cpp

#include "screen.h"

Screen::Screen(const std::string& name)
    : m_name{name}
{
    m_name = name;
}

Screen::Screen(const Screen& screen)
    : m_name{screen.m_name}
{

}

Screen::Screen(Screen&& screen)
    : m_name{std::move(screen.m_name)}
{

}

const std::string& Screen::name() const
{
    return this->m_name;
}

但我在编译时遇到问题:

screen.cpp:4: error: undefined reference to `vtable for Screen'

对于所有构造函数也是如此。
我不明白这是我的错误...请问,谁能解释一下?

【问题讨论】:

  • 如果你有一个非抽象的虚函数,那么你必须实现它。
  • 顺便说一下,如果你有虚函数并且意味着类是多态和继承的,你应该真正实现一个(虚拟)析构函数。
  • 一般来说,一个带有任何虚函数的类也应该有一个虚析构函数。
  • 在第一个构造函数中,m_name = name; 是多余的,因为 m_name{name} 成员初始值设定项。
  • @aschepler,是的,你是对的!当我尝试修复错误时忘记删除它。谢谢!

标签: c++ c++11


【解决方案1】:

您还必须实现Screen::draw

在典型的实现中,多态类的构造函数设置一个指向类的“vtable”的指针,其中包含指向类的虚函数的指针。由于您的第一个(也是唯一一个)虚函数丢失了,编译器无法生成这个 vtable,所以所有的构造函数都会在链接时抱怨它。

【讨论】:

  • 谢谢你和所有评论我的话题的人!效果很好!
  • @aschelper,很抱歉我的英语知识很差,但据我所知,我是否需要每次都实现一个 virtual 函数体,不是吗?
  • 非虚函数只有在被调用时才需要定义。必须始终定义非纯虚函数或析构函数。
  • @aschelper,看来,我抓住了你!感谢您的帮助!
【解决方案2】:

阿舍普勒所说的绝对正确。担心你的开始,你可能需要一些建议,什么时候应该使用虚函数。虚函数作为cpp中支持多态的一种方法,可以分为两种使用场景。

  1. 接口/抽象类

    在这种情况下,虚函数被声明为纯虚函数,其中一个类将被称为抽象类并且不可实例化。通过这样做,您可以像大多数现代编程支持一样实现“接口”。

    class Interface {
        //....
        virtual void f() = 0;
    };
    class Concrete {
        // override this f()
        void f() override {}
    };
    
  2. 多态/具体类

    在这种情况下,虚函数被声明为普通函数,但它可以被派生类覆盖。 而且你必须实现它

    class Parent {
        //...
        virtual void g();
    }
    class Derived {
        //...
        void g() override{}
    }
    

    请注意,您仍然可以声明一个与 parent 同名的函数,而不是声明为虚函数。这将被称为 hide,是另一个主题。

【讨论】:

  • 感谢您的详细解答!它对我来说变得更清楚了。
  • @Шах 不客气。
猜你喜欢
  • 1970-01-01
  • 2014-06-08
  • 1970-01-01
  • 2020-07-07
  • 2016-09-26
  • 1970-01-01
  • 2015-05-25
  • 2014-06-05
  • 2011-07-27
相关资源
最近更新 更多