我对多态性有一点问题。我的简单代码:
动物.h
class Animal {
public:
Animal();
Animal(const Animal& orig);
virtual ~Animal();
virtual void get();
};
动物.cpp
#include "Animal.h"
#include <iostream>
using namespace std;
Animal::Animal() {
cout << "Animal is born" << endl;
}
void Animal::get() {
cout << "get() from an Animal!" << endl;
}
鸟.h
class Bird : public Animal {
public:
Bird();
Bird(const Bird& orig);
virtual ~Bird();
void get();
};
鸟.cpp
#include "Bird.h"
#include <iostream>
using namespace std;
Bird::Bird() {
cout << "Bird is born" << endl;
}
void Bird::get() {
cout << "get() from a Bird!" << endl;
}
鸡.h
#include "Bird.h"
class Chicken : public Bird {
public:
Chicken();
Chicken(const Chicken& orig);
virtual ~Chicken();
void get();
};
鸡.cpp
#include "Chicken.h"
#include <iostream>
using namespace std;
Chicken::Chicken() {
cout << "Chicken is born" << endl;
}
void Chicken::get() {
cout << "get() from a Chicken!" << endl;
}
还有一个工厂方法根据输入返回一个指向具体实现的 Animal* 指针:
工厂.h
#include "Animal.h"
#include "Bird.h"
class Factory {
public:
Factory();
Factory(const Factory& orig);
virtual ~Factory();
Animal* generateAnimal();
Bird* generateBird();
};
工厂.cpp
#include "Factory.h"
#include "Animal.h"
#include "Bird.h"
#include "Chicken.h"
#include <iostream>
#include <string>
#include <stdlib.h>
using namespace std;
Animal* Factory::generateAnimal() {
string choice;
cout << "What do you want? 1-Animal, 2-Bird, 3-Chicken" << endl;
cin >> choice;
Animal* animal;
if (choice.at(0) == '1') {
cout << "You chose Animal" << endl;
animal = new Animal();
return animal;
} else if (choice.at(0) == '2') {
cout << "You chose Bird" << endl;
animal = new Bird();
return animal;
} else if (choice.at(0) == '3') {
cout << "You chose Chicken" << endl;
animal = new Chicken();
return animal;
} else {
cout << "Wrong input" << endl;
exit(1);
}
}
Bird* Factory::generateBird() {
string choice;
cout << "What do you want? 1-Animal, 2-Bird, 3-Chicken" << endl;
cin >> choice;
Bird* bird;
if (choice.at(0) == '2') {
cout << "You chose Bird" << endl;
bird = new Bird();
return bird;
} else if (choice.at(0) == '3') {
cout << "You chose Chicken" << endl;
bird = new Chicken();
return bird;
} else {
cout << "Wrong input" << endl;
exit(1);
}
}
我省略了ctors和dtors。
主文件
#include <cstdlib>
#include <iostream>
#include "Factory.h"
#include "Animal.h"
#include "Bird.h"
#include "Chicken.h"
using namespace std;
int main(int argc, char** argv) {
Factory factory;
Animal* animal = factory.generateAnimal();
animal->get();
return 0;
}
Animal 类的具体实现是在运行时解决的。很明显,从 Animal 类中删除virtual关键字会导致调用get()方法的 Animal 实现,无论 animal* 指向 Bird 还是 Chicken。
What do you want? 1-Animal, 2-Bird, 3-Chicken
3
You chose Chicken
Animal is born
Bird is born
Chicken is born
get() from an Animal!
同样明显的是,调用虚拟get()方法会导致对具体子类的多态调用。我担心的是这种情况:而不是
Animal* animal = factory.generateAnimal();
animal->get();
我们有
Bird* bird = factory.generateBird();
bird->get();
我们有一个指向 Bird 类的指针,其中get()方法没有被声明为虚拟的。输出是:
What do you want? 1-Animal, 2-Bird, 3-Chicken
3
You chose Chicken
Animal is born
Bird is born
Chicken is born
get() from a Chicken!
它是如何发生的,对非虚拟函数的调用导致对子类的虚拟调用?“虚拟主义”是否继承?如果是,是否有可能以某种方式对指针类执行非虚拟调用,而不是实现类?