虚函数与纯虚函数&构造函数与析构函数

一天接受两个挑战确实有点反应不过来。不过受到肯定说写博客是个好习惯,还是觉得有点小成就!继续坚持下去!等哪天回头来看自己已经能master那么多东西了就觉得真的在进步!
————————–>吐槽完毕。接下来是正文:

一、虚函数与纯虚函数

  1. 两者都在C++ OOP机制里面有着重要的作用,初学C++的时候没有仔细思考,现在回过头来总结发现其中还是有很多乐趣。通过用virtual关键词可以定义虚函数。
    友元函数 构造函数 static静态函数 不能用virtual关键字修饰;
    普通成员函数 和析构函数 可以用virtual关键字修饰;
    虚函数的作用主要是当基类指针引用的是子类,则基类指针会调用子类同名的方法。下面展示下代码:
    e.g 1
#include<iostream>
using namespace std;
class Base
{
public:
    Base()
    {
        cout << "This is Base\n";
    }
    virtual  void print()
    {
        cout << "This prints Base\n";
    }
    ~Base()
    {
        cout << "Destory Base\n";
    }
};
class Derived :public Base
{
public :
    Derived()
    {
        cout << "This is Derived\n";
    }
    void print()
    {
        cout << "This prints Derived\n";
    }
    ~Derived()
    {
        cout << "Destory Derived\n";
    }
};
int main()
{
    Derived *ptr_de=new Derived();
    Base *ptr_base = ptr_de;
    ptr_base->print();
    delete ptr_de;
    return 0;
}

输出结果:
This is Base
This is Derived
This prints Derived
Destory Derived
Destory Base
请按任意键继续…
2. 纯虚函数
请看代码:

class Base
{
public:
     Base()
    {
        cout << "This is Base\n";
    }
     virtual void print() = 0;
     ~Base()
    {
        cout << "Destory Base\n";
    }

};
class Derived : public Base
{
public :
    Derived()
    {
        cout << "This is Derived\n";
    }
    void print()
    {
        cout << "This prints Derived\n";
    }
    ~Derived()
    {
        cout << "Destory Derived\n";
    }
};

纯虚函数,即基类并不定义函数的具体实现,而由基类去实现,如示例中
virtual void print() = 0; 则提供了一个类似JAVA的接口,但是由子类去实现。如果基类的函数都是这样的,那么这个基类也称为抽象类。一般来说,抽象类是不能进行实例化的。但有时还是能通过其它途径。
可以看以下文章:抽象基类不能被实例化?看我怎么破!
不过抽象类的提出正是为了深刻表示出OOP的优势,所以个人觉得抽象基类不能实例化还是有其设计理念在。因此不予以继续说明。
3. 虚继承
说了一点虚函数和纯虚函数,接下来说一个虚继承。啥是虚继承?
请看以下代码:
e.g2

#include<iostream>
using namespace std;
class GrandFather
{
public:
    GrandFather() {}
     void fun()
    {
        cout << "GrandFather call function!" << endl;
    }

    virtual ~GrandFather()
    {
        cout << "GrandFather destruction!" << endl;
    }
};

class Father1 :virtual public GrandFather
{
public:
    Father1() {}
     void fun()
    {
        cout << "Father1 call function!" << endl;
    }

};

class Father2 : virtual public GrandFather
{
public:
    Father2() {}



};


class Son : public Father1,  public Father2
{
public:
    Son() {}

};

int main()
{
    Son* son = new Son;
    son->fun();

    return 0;
}

运行结果是输出father1的fun函数,如果father2也有fun函数,则编译失败,因为不明确调用哪个fun.
如果father1 father2均没有fun,则会调用grand father的fun函数。
虚拟继承是多重继承中特有的概念。虚拟基类是为解决多重继承而出现的。

二、构造函数与析构函数

初始化对象时,会先调用函数的构造函数。销毁对象则会调用析构函数。那么经典的问题是,二者的顺序问题。
由e.g 1可知,->构造函数的顺序是:基类,派生类.而析构函数的顺序刚好反过来。<-
那么如果加了virtual变为虚函数呢。
请看e.g 3

#include<iostream>
using namespace std;
class Base
{
public:
     Base()
    {
        cout << "This is Base\n";
    }
    virtual  void print()
    {
        cout << "This   prints Base\n";
    }
    virtual ~Base()
    {
        cout << "Destory Base\n";
    }
};
class Derived : public Base
{
public :
    Derived()
    {
        cout << "This is Derived\n";
    }
    void print()
    {
        cout << "This prints Derived\n";
    }
    ~Derived()
    {
        cout << "Destory Derived\n";
    }
};
int main()
{
    Derived *ptr_de=new Derived();
    Base *ptr_base = ptr_de;
    ptr_base->print();
    delete ptr_base; //这里与eg1比变化了,换做delete ptr_de的话效果也一样
    return   0;
}

输出结果:
This is Base
This is Derived
This prints Derived
Destory Derived
Destory Base
请按任意键继续…

那么如果把e.g1 delete ptr_de改为delete ptr_base呢,则会发生只销毁了基类,而派生类没被销毁。
因为e.g1 delete ptr_base,只会从调用对应类的析构方法,没有执行derived的析构方法,而加上virtual了,则基类指针会先销毁子类,然后才是基类。
若有e.g2的虚继承,则会先创建虚基类,然后按照顺序创建派生类的构造函数,析构函数则刚好相反。

End: 先总结至此,后续再补充!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值