理论
基类类型对象入口索引子类对象
1.泛化的概念:由具体的,个别的扩大为一般的;将此概念应用于结构体和类对象,就是泛化能力。类型泛化指的是在继承和派生时,基类派生出了很多不同的子类,形成了继承树,生成的子类都有自己独特的性质,但是所有的子类都有自己的独特性质,但是所有的子类都具有基类的性质,所以也可以看作是基类对象。
2.不同的子类对象都可以用基类指针索引到,但是如果用统一的方式索引到之后,遇到相同的函数入口,只会执行子类函数中的函数。也就是说,调用基类指针后,虽然指向的是派生类对象,但是调用的仍旧是基类的函数。如果想要调用派生类的话,应当将所有的同名函数设置为虚函数。
基类指针指向子类对象如何展现子类性质:虚函数
1.虚函数的概念:虚函数:在某基类中声明为 virtual 并在一个或多个派生类中被重新定义的成员函数。可以实现多态性。
2.动态绑定:虚函数和虚析构函数
含有虚函数的类要使用虚析构函数,否则容易导致派生类的资源无法释放。
派生类的构造函数是先构造的基类的无名对象,析构的时候按照基类的类型析构。
所以也会调用小模块的析构函数。
当基类指针指向派生类对象时,加上virtual就可以调用派生类的析构函数去析构派生类对象。
3.抽象类和纯虚函数
会发现有的类不需要产生对象,只是作为最顶层往下继承,每一个派生类的对象都是调用各自虚函数的函数体,因为基类里虚函数的函数体可以忽略,变成了纯虚函数,同时因为函数体不存在,也不能产生对象,变成了抽象类。
4.派生类构造函数执行的次序:
调用基类构造函数,调用顺序按照它们被继承时声明的顺序(从左到右);
调用内嵌成员对象的构造函数,调用顺序按照它们在类中声明的顺序;
派生类的构造函数体中的内容。
代码:
#include<bits/stdc++.h> #define PI 3.1415926 using namespace std; class Shape { protected: int width,height; public: Shape(){} Shape(int a,int b):width(a),height(b){} void set_values(int a,int b){ width=a;height=b;} virtual int area()=0;///纯虚函数 ~Shape(){} }; class circle:public Shape///圆 { public: circle(){} circle(int a,int b):Shape(a,b){} virtual int area(){ return width*width*PI;} }; class Rectangle:public Shape///矩形 { public: Rectangle(){} Rectangle(int a,int b):Shape(a,b){} virtual int area(){ return width*height;} ~Rectangle(){} }; class Triangle:public Shape///三角形 { public: Triangle(int a,int b):Shape(a,b){} virtual int area(){ return width*height/2;} ~Triangle(){} }; void Print_area(Shape& t1,Shape& t2,Shape& t3){ Shape* p1=&t1; cout<<p1->area()<<endl; p1=&t2; cout<<p1->area()<<endl; p1=&t3; cout<<p1->area()<<endl; } int main(){ Shape* p1; Rectangle rec_1(10,15); Triangle tri_1(10,6); circle cir_1(1,1); Print_area(rec_1,tri_1,cir_1); return 0; }
输出结果:
150
30
3