0
点赞
收藏
分享

微信扫一扫

C++虚函数和多态

代码敲到深夜 2022-04-20 阅读 90

虚函数和虚函数表

  • 什么是虚函数? 用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

举报

相关推荐

0 条评论