Ver*_*sed 1 c++ compiler-construction oop pointers
我刚刚开始学习 C++ 中的 OOP。我想知道为什么需要使用 virtual 关键字来指示编译器进行后期绑定?为什么编译器在编译时不能知道指针指向派生类?
class A {
public: int f() { return 'A';}
};
class B : public A {
public: int f() { return 'B';}
};
int main() {
A* pa;
B b;
pa = &b;
cout << pa->f() << endl;
}
Run Code Online (Sandbox Code Playgroud)
关于在编译时不知道,通常情况下行为仅在运行时才知道。考虑这个例子
#include <iostream>
struct A {};
struct B : A {};
struct C : A {};
int main()
{
int x;
std::cin >> x;
A* a = x == 1 ? new B : new C;
}
Run Code Online (Sandbox Code Playgroud)
在这个例子中,编译器如何知道是否a会指向 aB*或C*?它不能,因为行为取决于运行时值。
它怎么会(完全一般)?例如
#include <cstdlib>
struct Parent {};
struct Child : Parent {};
int main()
{
Parent* p = std::rand() % 2 ? new Parent() : new Child();
}
Run Code Online (Sandbox Code Playgroud)
假设您有一个简单的类层次结构,例如
class Animal
{
// Generic animal attributes and properties
};
class Mammal : public Animal
{
// Attributes and properties specific to mammals
};
class Fish : public Animal
{
// Attributes and properties specific to fishes
};
class Cat : public Mammal
{
// Attributes and properties specific to cats
};
class Shark : public Fish
{
// Attributes and properties specific to sharks
};
class Hammerhead : public Shark
{
// Attributes and properties specific to hammerhead sharks
};
Run Code Online (Sandbox Code Playgroud)
[有点啰嗦,但我想让“具体”类彼此远离]
现在让我们说我们有一个像
void do_something_with_animals(Animal* animal);
Run Code Online (Sandbox Code Playgroud)
最后让我们调用这个函数:
Fish *my_fish = new Hammerhead;
Mammal* my_cat = new Cat;
do_something_with_animals(my_fish);
do_something_with_animals(my_cat);
Run Code Online (Sandbox Code Playgroud)
现在,如果我们稍微思考一下,在do_something_with_animals函数中确实无法确切知道参数animal可能指向什么。是Mammal吗?一个Fish?特定的Fish子类型?
如果do_something_with_animals函数是在不同的翻译单元中定义的,这对编译器来说就更难了,而Mammal和Fish类(或其任何子类)的定义甚至可能不可用。