那么,为什么我必须在基数 class 中定义虚函数?
So, why do I have to define virtual function in a base class?
我正在尝试创建一个简单的基础抽象 class,其中包含一个虚函数和一个定义该虚函数的子 class。 运行 以下在编译期间会产生错误:
#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();
}
那么,为什么我必须在基类中定义虚函数class?
相比之下,在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();
}
}
您需要使用 = 0
.
在基础 class 中将其标记为“抽象”(或 C++ 术语中的“纯虚拟”)
class Animal {
public:
virtual void speak() = 0;
};
在 C++ 中,如果一个 class 至少有一个纯虚函数,则它是抽象的。
这个class
class Animal {
public:
virtual void speak();
};
不是抽象 class 因为在 class.
中没有声明纯虚函数
并且通过在 class 定义的函数声明中使用纯说明符来指定纯虚函数。
那就是让class抽象你应该像
一样声明它的虚函数
class Animal {
public:
virtual void speak() = 0;
};
编译器需要构建一个 table 指向虚函数的指针,其中将存储虚函数的实际地址。如果链接器无法解析虚函数的地址,则会发出错误。
请记住,可以定义纯虚函数。例如你可以写
class Animal {
public:
virtual void speak() = 0;
};
void Animal::speak()
{
std::cout << "The animal has issued a sound.\n";
}
在派生的 class 中,您可以通过以下方式定义函数
class Cat : public Animal{
public:
void speak() override {
Animal::speak();
cout << "Meow!";
}
};
是的,应该定义非纯虚函数。
A virtual function declared in a class shall be defined, or declared pure ([class.abstract]) in that class, or both; no diagnostic is required ([basic.def.odr]).
您可以提供定义,或将其标记为纯虚拟。
class Animal {
public:
virtual void speak() = 0;
};
我正在尝试创建一个简单的基础抽象 class,其中包含一个虚函数和一个定义该虚函数的子 class。 运行 以下在编译期间会产生错误:
#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();
}
那么,为什么我必须在基类中定义虚函数class?
相比之下,在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();
}
}
您需要使用 = 0
.
class Animal {
public:
virtual void speak() = 0;
};
在 C++ 中,如果一个 class 至少有一个纯虚函数,则它是抽象的。
这个class
class Animal {
public:
virtual void speak();
};
不是抽象 class 因为在 class.
中没有声明纯虚函数并且通过在 class 定义的函数声明中使用纯说明符来指定纯虚函数。
那就是让class抽象你应该像
一样声明它的虚函数class Animal {
public:
virtual void speak() = 0;
};
编译器需要构建一个 table 指向虚函数的指针,其中将存储虚函数的实际地址。如果链接器无法解析虚函数的地址,则会发出错误。
请记住,可以定义纯虚函数。例如你可以写
class Animal {
public:
virtual void speak() = 0;
};
void Animal::speak()
{
std::cout << "The animal has issued a sound.\n";
}
在派生的 class 中,您可以通过以下方式定义函数
class Cat : public Animal{
public:
void speak() override {
Animal::speak();
cout << "Meow!";
}
};
是的,应该定义非纯虚函数。
A virtual function declared in a class shall be defined, or declared pure ([class.abstract]) in that class, or both; no diagnostic is required ([basic.def.odr]).
您可以提供定义,或将其标记为纯虚拟。
class Animal {
public:
virtual void speak() = 0;
};