【虚函数的调用正中下怀】
代码展示
#include <iostream> using namespace std; class A { private: int number; public: A(int nu=21032114) :number(nu) {} virtual void show() { cout << "基类,学号为:" << number<<endl; } }; class B:public A { private: int score; public: B(int sc = 86) :score(sc) {} void show() { cout << "派生,成绩为:" << score<<endl; } }; int main() { A a; a.show(); B b; b.show(); A* p; p = &b; p->show(); //我想调用派生类,但仍然是基类的函数 A& p1 = b; b.show(); return 0; }
效果展示:
#include using namespace std;
class A { public:
virtual int fun() { return 1; } };
class E : public A { public:
virtual int fun() { return 5; } };
class B : virtual public A { public:
virtual int fun() { return 2; } };
class C : virtual public A { public:
virtual int fun() { return 3; } };
class D : public B, public C { public:
virtual int fun() { return 4; } };
int main() {
cout << sizeof(A) << endl; // 4
cout << sizeof(B) << endl; // 4
cout << sizeof© << endl; // 4
cout << sizeof(D) << endl; // 8
cout << sizeof(E) << endl; // 4
return 0; }
解释:
1.static静态成员变量不需计算
2.成员函数不占用空间
3.虚函数 有一个虚表指针占四个字节
A=4——> 4(A虚表指针)。
4.父类的与子类的同名虚函数,在继承的时候,子类会将父类的覆盖,
B=4------> 4(B虚表指针)
C=4------> 4(C虚表指针)
5.如果子类和父类都包含虚函数,但他们存放在一个虚表中,因此只要一个虚表指针。
D=8-------->4(D虚表指针)+4(D虚表指针)
E=4--------->4(B虚表指针)
(二)、虚基类
1.什么是虚基类:
当在多条继承路径上有一个公共的基类,在这些路径中的某几条汇合处,这个公共的基类就会产生多个实例(或多个副本),若只想保存这个基类的一个实例,可以将这个公共基类说明虚基类。所以可以说,虚基类是为了只实例化一次基类存在的。
2.虚基类的特点
(1):虚基类构造函数的参数必须由最新派生出来的类负责初始化(即使不是直接继承).
(2)虚基类的构造函数先于非虚基类的构造函数执行。
3.二义性的问题
1.问题所在:
代码展示:
#include <iostream> using namespace std; class Student { public: int age; int number; Student(int a, int nu) :age(a), number(nu) {} Student() {} void set() { cout << "请输入学生的年龄和学号" << endl; cin >> age >> number; } void show() { cout << "学生的年龄为:" << " " << "学号为:" << endl; } }; class Student1 :public Student { void show() { cout << "Student1的" << endl; } }; class Student2 :public Student{ void show() { cout << "Student2的" << endl;} }; class Student3 :public Student1,public Student2 { void show() { cout << "Student3的" << endl; } }; int main() { Student3 s3; s3.set(); return 0;}
效果展示:
2.【二义性的解决非虚基类正确示范】
代码展示
#include <iostream> using namespace std; class Student { public: int age; int number; Student(int a, int nu) :age(a), number(nu) {} Student() {} void set(){ cout << "请输入学生的年龄和学号" << endl; cin >> age >> number;} void show() { cout << "学生的年龄为:" << " " << "学号为:" << endl; } }; class Student1 :public Student { public: void show() { cout << "Student1的" << endl; } }; class Student2 :public Student { void show() { cout << "Student2的" << endl; } }; class Student3 :public Student1, public Student2 { void show() { cout << "Student3的" << endl; } }; int main() { Student3 s3; s3.Student1::set(); return 0; }
效果展示:
3.【二义性解决虚基类的方法正确示范】
#include <iostream> using namespace std; class Student { public: int age; int number; Student(int a, int nu) :age(a), number(nu) {} Student() {} void set(){ cout << "请输入学生的年龄和学号" << endl; cin >> age >> number;} void show() { cout << "学生的年龄为:" << " " << "学号为:" << endl; } }; class Student1 :virtual public Student { public: void show(){ cout << "Student1的" << endl;}}; class Student2 :virtual public Student { void show() { cout << "Student2的" << endl;} }; class Student3 :public Student1, public Student2 { void show() { cout << "Student3的" << endl;} }; int main() { Student3 s3; s3.set(); return 0; }
代码展示
(三)、纯虚函数
1.纯虚函数的作用
在许多情况下,在基类中不能对虚函数给出有意义的实现,而把它声明为纯虚函数,它的实现留给该基类的派生类去做。这就是纯虚函数的作用。
2.基本格式:
class <类名> { virtual <类型><函数名>(<参数表>)=0;… };
(四)、总结
虚基类
1, 一个类可以在一个类族中既被用作虚基类,也被用作非虚基类。
2, 在派生类的对象中,同名的虚基类只产生一个虚基类子对象,而某个非虚基类产生各自的子对象。
3, 虚基类子对象是由最新派生类的构造函数通过调用虚基类的构造函数进行初始化的。
4, 最派生类是指在继承结构中建立对象时所指定的类。
5, 派生类的构造函数的成员初始化列表中必须列出对虚基类构造函数的调用;如果未列出,则表示使用该虚基类的缺省构造函数。
6, 从虚基类直接或间接派生的派生类中的构造函数的成员初始化列表中都要列出对虚基类构造函数的调用。但只有用于建立对象的最派生 类的构造函数调用虚基类的构造函数,而该派生类的所有基类中列出的对虚基类的构造函数的调用在执行中被忽略,从而保证对虚基类子对象 只初始化一次。
7, 在一个成员初始化列表中同时出现对虚基类和非虚基类构造函数的调用时,虚基类的构造函数先于非虚基类的构造函数执行。
虚函数
1, 虚函数是非静态的、非内联的成员函数,而不能是友元函数,但虚函数可以在另一个类中被声明为友元函数。
2, 虚函数声明只能出现在类定义的函数原型声明中,而不能在成员函数的函数体实现的时候声明。
3, 一个虚函数无论被公有继承多少次,它仍然保持其虚函数的特性。
4, 若类中一个成员函数被说明为虚函数,则该成员函数在派生类中可能有不同的实现。当使用该成员函数操作指针或引用所标识的对象时 ,对该成员函数调用可采用动态联编。
5, 定义了虚函数后,程序中声明的指向基类的指针就可以指向其派生类。在执行过程中,该函数可以不断改变它所指向的对象,调用不同 版本的成员函数,而且这些动作都是在运行时动态实现的。虚函数充分体现了面向对象程序设计的动态多态性。 纯虚函数 版本的成员函数,而且这些动作都是在运行时动态实现的。虚函数充分体现了面向对象程序设计的动态多态性。
纯虚函数
1, 当在基类中不能为虚函数给出一个有意义的实现时,可以将其声明为纯虚函数,其实现留待派生类完成。
2, 纯虚函数的作用是为派生类提供一个一致的接口。
3, 纯虚函数不能实列化,