虚函数和虚函数表
-
什么是虚函数? 用virtual 修饰的成员函数叫做虚函数
-
虚函数对于类的影响
-
增加一个指针的内存,32位4个字节 ,64位就是8个字节
-
-
虚函数表(了解一下): 就是一个指针存储所有虚函数的首地址
#include <iostream>
using namespace std;
class MM
{
public:
virtual void print1()
{
cout << "虚函数1"<< endl;
}
virtual void print2()
{
cout << "虚函数2" << endl;
}
virtual void print3();
protected:
};
void MM::print3()
{
cout << "虚函数3" << endl;
}
class A
{
int age;
};
void testVirtual()
{
//C语言不允许存在空的结构体
cout << sizeof(MM) << endl; //空的类或者而结构体 占用1字节
cout << sizeof(A) << endl;
MM mm;
//虚函数表
int** vptr = (int **)&mm;
typedef void(*PF)();
PF func = (PF)vptr[0][0];
func(); //调用第一个虚函数
func = (PF)vptr[0][1];
func(); //调用第二个虚函数
}
int main()
{
testVirtual();
return 0;
}
虚函数和多态
-
多态定义: 同一种行为(调用)导致的不同的结果
-
多态的必要性原则
-
必须父类存在虚函数
-
子类必须采用public继承
-
必须存在指针的引用(使用)
#include <iostream> using namespace std; class Man { public: void WC1() { cout << "男人上厕所" << endl; } virtual void WC2() //父类必须要有virtual { cout << "龌龊男人上厕所" << endl; } protected: }; class Woman:public Man { public: void WC1() { cout << "女人上厕所" << endl; } void WC2() { cout << "女人上厕所" << endl; } protected: }; void testVirtual() { //正常访问不存在多态 cout << "正常访问,就近原则" << endl; Man man; man.WC1(); man.WC2(); Woman woman; woman.WC1(); woman.WC2(); cout << "指针访问,正常赋值" << endl; Man* pm = new Man; pm->WC1(); pm->WC2(); Woman* pw = new Woman; pw->WC1(); pw->WC2(); cout << "指针非正常赋值:子类对象初始化父类指针" << endl; Man* parent = new Woman; //有virtual看对象类型,没有virutal看指针 parent->WC1(); //不是虚函数 parent->WC2(); //是虚函数 parent = new Man; parent->WC2(); } //统一接口功能呢 void printInfo(Man* parent) { parent->WC2(); } class Shape { public: virtual void Draw() { cout << "绘制过程" << endl; } protected: }; class Rect :public Shape { public: void Draw() { cout << "画矩形" << endl; } protected: }; class Circle :public Shape { public: void Draw() { cout << "画圆" << endl; } protected: }; class Triangle :public Shape { public: void Draw() { cout << "绘制三角形" << endl; } }; class Ellipse :public Shape { public: void Draw() { cout << "绘制椭圆" << endl; } }; //降低因为变化而要修改代码 //采用增加代码方式满足新需求 //统一接口 class Tool { public: void draw(Shape* parent) { parent->Draw(); } }; int main() { testVirtual(); printInfo(new Woman); Tool* pTool = new Tool; pTool->draw(new Circle); pTool->draw(new Rect); pTool->draw(new Triangle); pTool->draw(new Ellipse); return 0; }
纯虚函数和ADT
-
纯虚函数也是虚函数只是纯虚函数是没有函数体的
-
virutal void print()=0; //在类中函数 这样写法
-
抽象类: 具有至少一个纯虚函数的类,叫做抽象类
-
抽象类不能构建对象
-
抽象类可以构建对象指针
-
-
纯虚函数没有被重写,无论被继承多少次 都是纯虚函数,虚函数无论被继承多少次都是虚函数
-
-
#include <iostream> using namespace std; //抽象类 class Parent { public: virtual void print()= 0; //纯虚函数 protected: }; void testAbstract() { //Parent object; 不能构建对象 Parent* parent = nullptr; } //纯虚函数就是做ADT(abstract data type 抽象数据类型)过程 //stack 栈 class stack { public: //父类中所有的操作描述好 virtual void push(int data) = 0; virtual void pop() = 0; virtual int top() const = 0; virtual bool empty() const = 0; virtual int size() const = 0; }; //子类想要创建对象,必须重写父类的纯虚函数 //ADT: 具有强迫性,所有子类重写函数必须和父类的一模一样 class arrayStack :public stack { public: void push(int data) { } void pop() { } int top() const { return 1; } bool empty() const { return true; } int size() const { return 1; } //可以增加别的函数 //可以增加别的成员 protected: int* array; }; struct Node { int data; Node* next; }; class listStack :public stack { public: void push(int data) { } void pop() { } int top() const { return 1; } bool empty() const { return true; } int size() const { return 1; } protected: Node* headNode; }; void testStack(stack* pStack) { pStack->push(1); while (!pStack->empty()) { cout << pStack->top(); pStack->pop(); } } class A { public: virtual void print() = 0; protected: }; class B :public A { public: void print() { cout << "B" << endl; } }; class C :public B { public: void print() { cout << "C" << endl; } }; void Abtract() { //B b; C c; //一般抽象类只被继承一次就重写 B* pc = new C; pc->print(); } int main() { testStack(new arrayStack); testStack(new listStack); Abtract(); return 0; }
虚析构函数
-
#include <iostream> using namespace std; class parent { public: //虚析构函数,不存在虚构造函数 virtual ~parent() { cout << "父类析构" << endl; } void print() {} protected: }; class son :public parent { public: void print() { } ~son() { cout << "子类析构" << endl; } }; int main() { //在用子类对象初始化父类指针,父类需要虚析构函数做内存释放 parent* p = new son; p->print(); delete p; return 0; }
C++类型转换
C++类型转换,专人做专事,传闻中C++中的更为安全。
const_cast
static_cast
dynamic_cast
reinterpret_cast