C++中的多态

1.下面的代码,可以帮助大家理解C++的多态。

#include <iostream>
using namespace std;
// 只要类中有一个纯虚函数,那么A就是一个抽象类
class A
{
public:
    //所有的接口,必须全部实现
    virtual void Eat() = 0;// 纯虚方法、方法,变成了接口
    virtual void Sleep() = 0;
    virtual void Foot() = 0;
};

class Dog:public A
{
public:
    virtual void Eat()//在子类里面virtual可以写,也可以不写
    {
        cout<<"Dog::Eat()"<<endl;
    }
    virtual void Sleep()
    {
        cout<<"Dog::Sleep()"<<endl;
    }
    virtual void Foot()
    {
        cout<<"Dog::Foot()"<<endl;
    }
};
class Cat : public A
{
public:
    virtual void Eat()//在子类里面virtual可以写,也可以不写
    {
        cout<<"Cat::Eat()"<<endl;
    }
    virtual void Sleep()
    {
        cout<<"Cat::Sleep()"<<endl;
    }
    virtual void Foot()
    {
        cout<<"Cat::Foot()"<<endl;
    }

};
class Bird : public A
{
public:
    virtual void Eat()//在子类里面virtual可以写,也可以不写
    {
        cout<<"Bird::Eat()"<<endl;
    }
    virtual void Sleep()
    {
        cout<<"Bird::Sleep()"<<endl;
    }
    virtual void Foot()
    {
        cout<<"Bird::Foot()"<<endl;
    }
public:
    virtual void Fly()
    {
        cout<<"Bird::Fly()"<<endl;
    }
};
class Ostrich : public Bird// 鸵鸟公有继承鸟类
{
private:
    void Fly()
    {
        cout<<"Bird::Fly()"<<endl;
    }
};
//统一的接口
void Active(A *pa)
{
    pa->Eat();
    pa->Foot();
    pa->Sleep();
}
int main()
{
    Ostrich oo;
    oo.Sleep();
   // A a;//不能实例化A,A是个抽象基类
    Dog d;
    Cat c;
    Active(&d);
    Active(&c);
}

2.探究多态的深层次原因

#include <iostream>
using namespace std;
class Base
{
public:
    virtual void func(){
        cout<<"Base::func()"<<endl;
    }
private:
    int x;
};
class D: public Base
{
public:
    void func(){
        cout<<"D::func()"<<endl;
    }
private:
    int y;
};

int main()
{
    cout<< sizeof(D)<<endl;// 有虚指针的话大小为12(x,y,虚指针),没有虚指针的话大小为8(x,y)
    D d;
}
#include <iostream>
using namespace std;
class Base
{
public:
    Base():y(0){
        cout<<"Create Base object"<<endl;
    }

public:
    virtual void func(){
        cout<<"Base::func()"<<endl;
    }
    virtual void list(){
        cout<<"Base::list()"<<endl;
    }
	virtual void show(){
        cout<<"Base::show()"<<endl;
    }
    void print(){
        cout<<"Base::print()"<<endl;
    }
private:
    int y;
};
class D: public Base
{
public:
    D():x(0){
        cout<<"Create D object"<<endl;
    }
public:
    void func(){
        cout<<"D::func()"<<endl;
    }
     void list(){
        cout<<"D::list()"<<endl;
    }
     void print(){
        cout<<"D::print()"<<endl;
    }

private:
    int x;
};

int main()
{
    //cout<< sizeof(D)<<endl;
    D d;
    Base *pb = &d;//用父类的指针去接收子类对象的地址
    pb->func();
    return 0;
}

运行之后虚表的结构:

 

class Base 
{ 
public: 
	virtual void f()
	{ cout << "Base::f"<<endl;}
	virtual void g()
	{ cout << "Base::g"<<endl;}
	virtual void h()
	{ cout << "Base::h"<<endl;}
private:
	int a;
	int x;
}; 

typedef void(*pFun)();

void main()
{
	Base b;
	cout<<"&b = "<<&b<<endl;
	cout<<"vfptr = "<<hex<<*(int*)(&b)<<endl;

	pFun pfun = (pFun)*(((int*)*(int*)(&b))+0);
	pfun();
	pfun = (pFun)*(((int*)*(int*)(&b))+1);
	pfun();
	pfun = (pFun)*(((int*)*(int*)(&b))+2);
	pfun();
}

从上面的代码证明了虚表的存在,我们可以分别取出在虚表中的函数,并执行这些函数。

上图可以看出来pfun指的是虚表中存储的第一个函数。单步调试往下执行,可以分别取出虚表中的函数。


#include<iostream>
using namespace std;
class Base
{
public:
	Base()
	{
		cout<<"Create Base."<<endl;
	}
	virtual~Base()
	{
		cout<<"Free Base."<<endl;
	}
};
class D : public Base
{
public:
	D()
	{
		cout<<"Create D."<<endl;
	}
	~D()
	{
		cout<<"Free D."<<endl;
	}
};

void main()
{
	//D d;
	Base *pb = new D;
	delete pb;
}

基类指针,指向子类的对象(动态开辟空间),基类的析构函数加virtual,那么在析构pb时候,在析构完子类的时候,会自动的析构父类。

#include<iostream>
using namespace std;
class Base1 
{ 
public: 
	virtual void f()
	{ cout << "Base::f"<<endl;}
	virtual void g()
	{ cout << "Base::g"<<endl;}
	virtual void h()
	{ cout << "Base::h"<<endl;}
};
class Base2
{ 
public: 
	virtual void f()
	{ cout << "Base::f"<<endl;}
	virtual void g()
	{ cout << "Base::g"<<endl;}
	virtual void h()
	{ cout << "Base::h"<<endl;}
};
class Base3 
{ 
public: 
	virtual void f()
	{ cout << "Base::f"<<endl;}
	virtual void g()
	{ cout << "Base::g"<<endl;}
	virtual void h()
	{ cout << "Base::h"<<endl;}
};

class D : public Base1, public Base2, public Base3
{ 
public: 
	virtual void f()
	{ cout << "D::f"<<endl;}
	virtual void g1()
	{ cout << "D::g"<<endl;}
	virtual void h1()
	{ cout << "D::h"<<endl;}
};

void main()
{
	D d;
}

多继承的时候,子类中重写的方法会覆盖父类虚表中的方法,三个虚表每个都要覆盖。没有重写的会跟在虚表的后面。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值