C++学习笔记——类和对象——多态

多态是C++面向对象的三大特性之一。

多态的分类:

静态多态:函数重载和运算符重载属于静态多态,函数名的复用;

动态多态:通过派生类和虚函数实现运行时多态。

静态多态和动态多态的区别

静态多态的函数地址在程序编译阶段确定;

动态多态的函数地址在程序运行阶段确定。

下面是一个简单的例子:

class Fruit{
public:
//    函数前面加上virtual关键字,编译器在编译阶段就不能确定函数调用了
    virtual void func(){
        cout<<"这是一个水果"<<endl;
    }
};

class Apple:public Fruit{
public:
    void func(){
        cout<<"这是一个苹果"<<endl;
    }
};

class Orange:public Fruit{
public:
    void func(){
        cout<<"这是一个橘子"<<endl;
    }
};

void visit(Fruit &fruit){
    fruit.func();
}

void test01(){
    Apple apple;
    visit(apple);

    Orange orange;
    visit(orange);
}

可以看出多态的使用要满足下面的条件:

1.有继承关系;

2.子类重写父类中的虚函数;

3.使用时父类指针或者引用指向子类对象。

多态的优点:

1.代码组织结构清晰;

2.代码可读性强;

3.有利用扩展和维护。

下面是一个简单的计算器的类,可以更好的看出多态的优点。

class BaseCalculator{
public:
    virtual int get_result(){
        return 0;
    }

public:
    int m_a;
    int m_b;
};
class AddCalculator:public BaseCalculator{
public:
    int get_result(){
        return m_a+m_b;
    }
};
class SubCalculator:public BaseCalculator{
public:
    int get_result(){
        return m_a-m_b;
    }
};
class MulCalculator:public BaseCalculator{
public:
    int get_result(){
        return m_a*m_b;
    }
};
void test01(){
//    创建加法计算器
    BaseCalculator *a=new AddCalculator;
    a->m_a=5;
    a->m_b=6;
    cout<<a->get_result()<<endl;
//    用完要销毁
    delete a;

//    创建乘法计算器
    a=new MulCalculator;
    a->m_a=6;
    a->m_b=4;
    cout<<a->get_result()<<endl;
    delete a;

//    创建减法计算器
    a=new SubCalculator;
    a->m_a=15;
    a->m_b=6;
    cout<<a->get_result()<<endl;
    delete a;
}

纯虚函数和抽象类:

在多态中,可以将父类中的虚函数改为纯虚函数,当类中有了纯虚函数,这个类可以被称为抽象类。

纯虚函数语法:

virtual 返回值类型 函数名 (参数列表)=0;

抽象类的特点:

1.不能实例化对象;

2.子类必须重写抽象类中的纯虚函数,否则也是抽象类。

下面是一个小例子:

class Base{
public:
    virtual void func()=0;
};

class Son:public Base{
public:
    virtual void func(){
        cout<<"Son中func的调用"<<endl;
    }
};
void test01(){
//    因为抽象类无法实例化对象,所以先赋一个NULL
    Base *base=NULL;
    base=new Son;
    base->func();
    delete base;
}

虚析构和纯虚析构:

在使用多态时,如果子类中有属性开辟到堆区,那么父类指针在释放时无法调用到子类的析构代码,这是需要解决的问题。

解决方法:

将父类中的析构函数改为虚析构或者纯虚析构。

虚析构和纯虚析构的比较;

共同点;

1.可以解决父类指针释放子类对象;

2.需要有具体的实现。

区别:

如果是纯虚析构,则该类属于抽象类,无法实例化对象。

虚析构语法:

virtual ~类名(){}

纯虚析构语法:

virtual ~类名()=0;

类名::~类名(){}

class Base{
public:
    Base(){
        cout<<"Base构造函数调用"<<endl;
    }
    virtual void func()=0;
//    纯虚析构函数
    virtual ~Base()=0;
};

Base::~Base() {
    cout<<"Base析构函数调用"<<endl;
}

class Son:public Base{
public:
    Son(string name){
        cout<<"Son构造函数调用"<<endl;
        m_name=new string(name);
    }
    virtual void func(){
        cout<<"这是"<<*m_name<<endl;
    }
    ~Son(){
        cout<<"Son析构函数调用"<<endl;
        if(this->m_name!=NULL){
            delete m_name;
//            置为NULL防止出现野指针
            m_name=NULL;
        }
    }
public:
    string *m_name;
};
void test01(){
    Base *base=new Son("tonny");
    base->func();
    delete base;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值