day09 -多态

多态

默认情况下,编译器只会根据指针类型调用对应的函数,不存在多态

  • 多态是面向对象非常重要的一个特性
    • 同一操作作用于不同的对象,可以有不同的解释,产生不同的执行结果
    • 在运行时,可以识别出真正的对象类型,调用对应子类中的函数
  • 多态的要素
    • 子类重写父类的成员函数(override)
    • 父类指针指向子类对象
    • 利用父类指针调用重写的成员函数
/*
面向对象的3大特性:
封装
继承
多态

重写(override):子类重写(覆盖)父类的方法
重载(overload)
*/

class Animal {
public:
	virtual void run() {
		cout << "Animal::run()" << endl;
	}
};

class Dog : public Animal {
public:
	void run() {
		cout << "Dog::run()" << endl;
	}
};

class ErHa : public Dog {
public:
	void run() {
		cout << "ErHa::run()" << endl;
	}
};

int main() {
	/*Animal *animal0 = new Animal();
	animal0->run();

	Animal *animal1 = new Dog();
	animal1->run();

	Animal *animal2 = new ErHa();
	animal2->run();*/

	Dog *dog0 = new Dog();
	dog0->run();

	Dog *dog1 = new ErHa();
	dog1->run();

	getchar();
	return 0;
}

虚函数

  • C++中的多态通过虚函数(virtual function)来实现
  • 虚函数:被virtual修饰的成员函数
  • 只要在父类中声明为虚函数,子类中重写的函数也自动变成虚函数(也就是说子类中可以省略virtual关键字)
class Animal {
public:
	int m_age;
	virtual void speak() {
		cout << "Animal::speak()" << endl;
	}
	virtual void run() {
		cout << "Animal::run()" << endl;
	}
};

class Cat : public Animal {
public:
	int m_life;
	Cat() :m_life(0) {}
	void speak() {
		cout << "Cat::speak()" << endl;
	}
	void run() {
		cout << "Cat::run()" << endl;
	}
};


int main() {
	cout << sizeof(Animal) << endl;

	// cout << sizeof(Cat) << endl;
	/*Animal *animal = new Animal();

	Animal *cat1 = new Cat();
	cat1->speak();
	cat1->run();
	Animal *cat2 = new Cat();
	Animal *cat3 = new Cat();*/

	Animal *animal1 = new Animal();
	animal1->m_age = 10;
	animal1->run();

	Animal *animal2 = new Cat();
	animal2->run();


	getchar();
	return 0;
}
  • 虚函数的实现原理是虚表,这个虚表里面存储着最终需要调用的虚函数地址,这个虚表也叫虚函数表
  • 所有的Cat对象(不管在全局区、栈、堆)共用同一份虚表

虚析构函数

  • 含有虚函数的类,应该将析构函数声明为虚函数(虚析构函数)
  • delete父类指针时,才会调用子类的析构函数,保证析构的完整性

纯虚构函数

  • 纯虚函数:没有函数体且初始化为0的虚函数,用来定义接口规范
  • 抽象类(Abstract Class)
    • 含有纯虚函数的类,不可以实例化(不可以创建对象)
    • 抽象类也可以包含非纯虚函数
    • 如果父类是抽象类,子类没有完全实现纯虚函数,那么这个子类依然是抽象类
// 类似于Java中接口、抽象类
// 类似于OC中的协议protocol

// Animal是个抽象类
class Animal {
public:
	virtual void speak() = 0;
	virtual void run() = 0;
};

class Cat : public Animal {
public:
	void run() {

	}
};

class WhiteCat : public Cat {
public:
	void speak() {

	}
	void run() {

	}
};

int main() {
	Cat *cat = new WhiteCat();

	getchar();
	return 0;
}
posted @ 2021-04-18 20:18  AAAAAAAAA123123  阅读(40)  评论(0编辑  收藏  举报