在C++中,可以通过将一个子类的对象赋值给一个指向父类的指针,来实现多态。这是通过对象的指针或引用来使用多态性的一种方式。当使用这种方法时,可以通过父类的指针或引用来访问子类的成员,但是只能访问到父类声明的成员,而不能访问子类新增的成员。
以下是一个简单的示例:
#include <iostream>
class Animal {
public:
// 默认构造函数
Animal() {
std::cout << "Animal default constructor\n";
}
// 带参数的构造函数
Animal(const std::string& name) : name(name) {
std::cout << "Animal parameterized constructor\n";
}
virtual void makeSound() const {
std::cout << "Some generic sound\n";
}
void myFun()
{
std::cout << " Animal myFun()\n";
}
void myFun2()
{
std::cout << " 父类中有,子类中没有\n";
}
protected:
std::string name;
};
class Dog : public Animal {
public:
// 默认构造函数
Dog() {
std::cout << "Dog default constructor\n";
}
// 带参数的构造函数
Dog(const std::string& name, const std::string& breed) : Animal(name), breed(breed) {
std::cout << "Dog parameterized constructor\n";
}
void makeSound() const override {
std::cout << "Bark Bark!\n";
}
void fetch() const {
std::cout << "子类中有,父类中没有\n";
}
void myFun()
{
std::cout << " Dog myFun()\n";
}
private:
std::string breed;
};
int main() {
// 使用默认构造函数创建 Animal 对象
Animal* animalPtr = new Animal();
animalPtr->makeSound(); //调用的是父类的成员函数
delete animalPtr;
std::cout << "--------------------------------\n";
Animal* animalPtr2 = new Dog(); //调用 父类的构造函数 子类的构造函数
animalPtr2->makeSound(); //因为,子类重写了父类的虚函数所以,调用的是子类的成员函数
animalPtr2->myFun(); //因为myFun不是虚函数 调用是根据指针类型来调用的,所以调用的是父类的成员函数
animalPtr2->myFun2(); //会调用
//animalPtr2->fetch();//会报错 无法通过 animalPtr 访问 Dog 类的 fetch 函数,因为它是 Animal 类型的指针
delete animalPtr2;
std::cout << "--------------------------------\n";
//调用 父类的构造函数 子类的构造函数 构造函数的调用顺序是按照继承关系的顺序进行的。
// 首先调用基类(父类)的构造函数,然后调用派生类(子类)的构造函数。
Dog* animalPtr3 = new Dog();
animalPtr3->makeSound(); //调用的是子类的成员函数
animalPtr3->myFun(); //调用的是子类的成员函数
animalPtr3->myFun2(); //会调用
animalPtr3->fetch();
delete animalPtr3;
std::cout << "--------------------------------\n";
// 在使用继承时,将派生类的对象赋值给基类类型的指针可以实现多态,允许通过基类指针访问派生类对象,
// 从而实现运行时动态绑定。这对于实现抽象接口和处理多个派生类对象的情况非常有用。
return 0;
}
- 继承和多态的机制允许基类指针指向派生类对象,从而实现对派生类对象的访问和操作。
- 虚函数允许在派生类中重写基类的函数,实现运行时动态绑定。
- 构造函数调用的顺序是按照继承关系的顺序进行的,先调用基类构造函数,再调用派生类构造函数。
- 派生类对象可以通过基类指针进行访问,但只能访问基类中的成员和派生类中重写的虚函数。非虚函数则根据指针类型来决定调用哪个版本。