构造函数中未定义对“vtable”的引用

Шах*_*Шах 2 c++ c++11

我尝试学习 C++ 构造函数,我还是菜鸟。我写了下一堂课:
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
Run Code Online (Sandbox Code Playgroud)

屏幕.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;
}
Run Code Online (Sandbox Code Playgroud)

但我在编译时遇到一个问题:

screen.cpp:4: 错误:未定义对“屏幕 vtable”的引用

对于所有构造函数也是如此。
我不明白这是我的错误...请问有人可以解释我吗?

asc*_*ler 5

您还必须实施Screen::draw.

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


Fra*_*ang 5

阿谢普勒所说的完全正确。考虑到您的开始,您可能需要一些关于何时应该使用虚拟函数的建议。虚拟函数作为cpp中支持多态性的方法,可以分为两种使用场景。

  1. 接口/抽象类

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

    class Interface {
        //....
        virtual void f() = 0;
    };
    class Concrete: public Interface {
        // override this f()
        void f() override {}
    };
    
    Run Code Online (Sandbox Code Playgroud)
  2. 多态/具体类

    在这种情况下,虚函数被声明为普通函数,只是它可以被派生类重写。并且你必须执行它

    class Parent {
        //...
        virtual void g();
    }
    class Derived: public Parent {
        //...
        void g() override{}
    }
    
    Run Code Online (Sandbox Code Playgroud)

请注意,您仍然可以声明与父函数同名的函数,该函数未声明为虚函数。这将被称为hide,并且是另一个主题。