C++中对C的扩展学习新增内容———面向对象(继承)函数扩展性及虚函数机制
1、c语言中的多态,动态绑定和静态绑定
void do_speak(void(*speak)()) { speak(); } void pig_speak() { cout << "猪叫..." << endl; } void cat_speak() { cout << "猫叫..." << endl; } void test01() { do_speak(cat_speak); }
C++中的多态:
class Animal { public: // 虚函数 virtual void speak() { cout << "动物在叫唤..." << endl; } void func() { } }; class Cat : public Animal { public: Cat(string name) { m_name = name; } void speak() { cout << m_name << " 在叫唤..." << endl; } void func() { } public: string m_name; }; class Dog : public Animal { public: Dog(string name) { m_name = name; } void speak() { cout << m_name << " 在汪汪..." << endl; } void func() { } public: string m_name; }; class Pig : public Animal { public: void speak() { cout << " 猪在叫..." << endl; } };
1、静态绑定
(1) 编译器会根据指针类型、引用类型来确定函数调用。
(2) 如果要实现根据传递不同对象,调用不同对象的speak,就要进行动态绑定。
2、动态绑定
(1) 根据引用或者指针,实际指向的类型来确定函数调用。
(2) 虚函数机制可以让编译器实现动态绑定。
3、实现多态的条件
(1) 表现形式:父类指针或者引用指向子类对象。
(2) 父类必须要有虚函数。
(3) 子类必须重写父类的虚函数,如果不重写,默认调用的父类函数。
(4) 父类纸质恩、或者引用指向子类对象。
虚函数的机制:
1、如果类的内部包含了虚函数,编译器首先会在类中安插虚函数表指针vfptr,vfptr指向一张表,这张表中存储的类中所有的虚函数入口地址。
2、当子类继承了父类,会将父类的虚函数表指针继承下来。一开始该虚函数指针指向父类的虚函数表,在子类中的构造函数中,编译器将其重新指向到了子类自己的虚函数表。
3、当子类重写了父类的虚函数,在虚函数表中会用子类的虚函数地址去覆盖父类对应虚函数的函数地址。
4、当通过父类指针、引用调用函数时,编译器会先找到该对象中隐藏存储的vfptr指针,根据虚函数指针找到虚函数表,在虚函数表中找到对应的函数入口地址,进行执行。
虚函数代码实现:
class Animal { public: // 虚函数 virtual void speak() { cout << "动物在叫唤..." << endl; } void func() { } }; class Cat : public Animal { public: Cat(string name) { m_name = name; } void speak() { cout << m_name << " 在叫唤..." << endl; } void func() { } public: string m_name; }; class Dog : public Animal { public: Dog(string name) { m_name = name; } void speak() { cout << m_name << " 在汪汪..." << endl; } void func() { } public: string m_name; }; class Pig : public Animal { public: void speak() { cout << " 猪在叫..." << endl; } };