c++ 为什么我必须在基类中定义虚函数?

rsl1atfo  于 2023-02-06  发布在  其他
关注(0)|答案(3)|浏览(157)

我试图创建一个简单的抽象基类,它包含一个虚函数和一个定义该虚函数的子类。运行下面的代码会在编译过程中产生错误:

#include <iostream>
using namespace std;

class Animal {
public:
    virtual void speak();

};

class Cat : public Animal{
public:
    void speak() override {
        cout << "Meow!";
    }
};

int main() {
    Cat cat;
    Animal* base = &cat;
    base->speak();
}
// error LNK2001: unresolved external symbol "public: virtual void __thiscall Base::speak(void)" (?speak@Base@@UAEXXZ)

我的IDE建议在Animal中为speak()添加一个无用的定义,它起作用了:

#include <iostream>
using namespace std;

class Animal {
public:
    virtual void speak();
};

void Animal::speak() {

}

class Cat : public Animal{
public:
    void speak() override {
        cout << "Meow!";
    }
};

int main() {
    Cat cat;
    Animal* base = &cat;
    base->speak();
}

那么,为什么我必须在基类中定义虚函数呢?
相比之下,在Java中没有这样的需要,甚至没有这样的可能性(这更有意义):

abstract class Animal {
    abstract void speak();
}

class Cat extends Animal {
    void speak() {
        System.out.println("Meow!");
    }
}

public class Main {
    public static void main(String[] args) {
        Animal animal = new Cat();
        animal.speak();
    }
}
pw9qyyiw

pw9qyyiw1#

是,需要定义非纯虚函数。
[类.虚拟]/12:
类中声明的虚函数应在该类中定义或声明为纯函数(class.abstract(https://timsong-cpp.github.io/cppwp/class.abstract)),或同时定义和声明;不需要诊断(basic.def.odr(https://timsong-cpp.github.io/cppwp/basic.def.odr))。
您可以提供一个定义,或者将其标记为纯虚拟。

class Animal {
public:
    virtual void speak() = 0;
};
6jygbczu

6jygbczu2#

您需要使用= 0在基类中将其标记为“abstract”(或C++术语中的“pure virtual”)。

class Animal {
public:
    virtual void speak() = 0;
};
nkoocmlb

nkoocmlb3#

在C++中,如果一个类至少有一个纯虚函数,那么它就是抽象的。
这个班

class Animal {
public:
    virtual void speak();

};

不是抽象类,因为该类中未声明纯虚函数。
虚函数通过在类定义的函数声明中使用pure说明符来指定为pure。
也就是说,要使类抽象化,应该声明其虚函数,如下所示

class Animal {
public:
    virtual void speak() = 0;

};

编译器需要建立一个指向虚函数的指针表,其中存储虚函数的实际地址。如果链接器无法解析虚函数的地址,则会发出错误。
请记住,可以定义纯虚函数。例如,您可以编写

class Animal {
public:
    virtual void speak() = 0;

};

void Animal::speak()
{
    std::cout << "The animal has issued a sound.\n";
}

在派生类中,您可以按以下方式定义函数

class Cat : public Animal{
public:
    void speak() override {
        Animal::speak();
        cout << "Meow!";
    }
};

相关问题