溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

C++--被遺棄的多重繼承、經(jīng)典問題

發(fā)布時(shí)間:2020-07-20 22:16:39 來源:網(wǎng)絡(luò) 閱讀:570 作者:淡淡_小孩 欄目:編程語言

一.被遺棄的多重繼承

Q:C++中是否允許一個(gè)類繼承自多個(gè)父類?
在實(shí)際的C++編譯環(huán)境中,C++是支持編寫多重繼承的代碼
1.一個(gè)子類可以擁有多個(gè)父類
2.子類擁有所有父類的成員變量
3.子類繼承所有父類的成員函數(shù)
4.子類對象可以當(dāng)作任意父類對象使用
多重繼承的語法規(guī)則
C++--被遺棄的多重繼承、經(jīng)典問題
但是在多重繼承中會存在許多問題
Q:多重繼承得到的對象可能擁有不同的地址
代碼示例

#include <iostream>
#include <string>

using namespace std;

class BaseA
{
    int ma;
public:
    BaseA(int a)
    {
        ma = a;
    }
    int getA()
    {
        return ma;
    }
};

class BaseB
{
    int mb;
public:
    BaseB(int b)
    {
        mb = b;
    }
    int getB()
    {
        return mb;
    }
};

class Derived : public BaseA, public BaseB//擁有兩個(gè)父類
{
    int mc;
public:
    Derived(int a, int b, int c) : BaseA(a), BaseB(b)
    {
        mc = c;
    }
    int getC()
    {
        return mc;
    }
    void print()
    {
        cout << "ma = " << getA() << ", "
             << "mb = " << getB() << ", "
             << "mc = " << mc << endl;
    }
};

int main()
{
    cout << "sizeof(Derived) = " << sizeof(Derived) << endl;   

    Derived d(1, 2, 3);

    d.print();

    cout << "d.getA() = " << d.getA() << endl;
    cout << "d.getB() = " << d.getB() << endl;
    cout << "d.getC() = " << d.getC() << endl;

    cout << endl;
    //兩個(gè)父類指針指向同一個(gè)對象
    BaseA* pa = &d;
    BaseB* pb = &d;

    cout << "pa->getA() = " << pa->getA() << endl;
    cout << "pb->getB() = " << pb->getB() << endl;

    cout << endl;

    void* paa = pa;
    void* pbb = pb;

    if( paa == pbb )
    {
        cout << "Pointer to the same object!" << endl; 
    }
    else
    {
        cout << "Error" << endl;
    }

    cout << "pa = " << pa << endl;
    cout << "pb = " << pb << endl;
    cout << "paa = " << paa << endl;
    cout << "pbb = " << pbb << endl; 

    return 0;
}

運(yùn)行結(jié)果
C++--被遺棄的多重繼承、經(jīng)典問題
我們可以看到在條件判斷語句中,paa與pbb指向的是同一個(gè)對象,按理說應(yīng)該打印相同時(shí)的語句,可是卻打印錯(cuò)誤,從接下來的地址打印結(jié)果是不一樣的,這就造成了多重繼承的問題--同一個(gè)對象取地址之后進(jìn)行初始化,但是pa與pb打印的結(jié)果卻不同
C++--被遺棄的多重繼承、經(jīng)典問題
Q:多重繼承可能產(chǎn)生冗余的成員
C++--被遺棄的多重繼承、經(jīng)典問題
代碼實(shí)現(xiàn)

#include <iostream>
#include <string>

using namespace std;

class People
{
    string m_name;
    int m_age;
public:
    People(string name, int age)
    {
        m_name = name;
        m_age = age;
    }
    void print()
    {
        cout << "Name = " << m_name << ", "
             << "Age = " << m_age << endl;
    }
};

class Teacher : virtual public People
{
public:
    Teacher(string name, int age) : People(name, age)
    {
    }
};

class Student : virtual public People
{
public:
    Student(string name, int age) : People(name, age)
    {
    }
};

class Doctor : public Teacher, public Student
{
public:
    Doctor(string name, int age) : Teacher(name, age), Student(name, age), People(name, age)
    {
    }
};

int main()
{
    Doctor d("Delphi", 33);

    d.print();

    return 0;
}

C++--被遺棄的多重繼承、經(jīng)典問題
由運(yùn)行結(jié)果可以知道,在進(jìn)行print時(shí)出錯(cuò),這是因?yàn)镈octor由于繼承,會有兩個(gè)打印的函數(shù),所以通過作用域分辨符進(jìn)行改正
由于冗余,打印的結(jié)果可能不一樣
C++--被遺棄的多重繼承、經(jīng)典問題
當(dāng)多重繼承關(guān)系出現(xiàn)閉合時(shí)將產(chǎn)生暑假冗余的問題
解決方案:虛繼承
C++--被遺棄的多重繼承、經(jīng)典問題

二.經(jīng)典問題分析

一.關(guān)于動態(tài)內(nèi)存分配
Q:new和malloc的區(qū)別?delete和free的區(qū)別?
A.new關(guān)鍵字與malloc函數(shù)的區(qū)別
1.new關(guān)鍵字是C++的一部分,malloc是由C庫提供的函數(shù)
2.new以具體類型為單位進(jìn)行內(nèi)存分配,malloc以字節(jié)為單位進(jìn)行內(nèi)存分配
3.new在申請內(nèi)存空間時(shí)可進(jìn)行初始化,malloc僅根據(jù)需要申請定量的內(nèi)存空間
代碼示例

#include <iostream>
#include <string>
#include <cstdlib>

using namespace std;

class Test
{
    int* mp;
public:
    Test()
    {
        cout << "Test::Test()" << endl;

        mp = new int(100);

        cout << *mp << endl;
    }
    ~Test()
    {
        delete mp;

        cout << "~Test::Test()" << endl;
    }
};

int main()
{
    Test* pn = new Test;
    Test* pm = (Test*)malloc(sizeof(Test));

    delete pn;
    free(pm);

    return 0;
}

運(yùn)行結(jié)果
C++--被遺棄的多重繼承、經(jīng)典問題
關(guān)于動態(tài)內(nèi)存分配
new和malloc的區(qū)別
1.new在所有C++編譯器中都能被支持,malloc在某些系統(tǒng)開發(fā)中是不能調(diào)用的
2.new能夠觸發(fā)析構(gòu)函數(shù)的調(diào)用,malloc僅分配需要的內(nèi)存空間
3.對象的創(chuàng)建只能使用new,malloc不適合面向?qū)ο箝_發(fā)
delete和free的區(qū)別
1.delete在所有C++編譯器中都被支持,free在某些系統(tǒng)開發(fā)中是不能調(diào)用的
2.delete能夠觸發(fā)析構(gòu)函數(shù)的調(diào)用,free僅歸還之前的分配空間
3.對象的銷毀只能使用delete,free不適合面向?qū)ο蟮拈_發(fā)

B.關(guān)于虛函數(shù)
Q:構(gòu)造函數(shù)是否可以成為虛函數(shù)?析構(gòu)函數(shù)是否可以成為虛函數(shù)?
1.構(gòu)造函數(shù)不可能成為虛函數(shù)--在構(gòu)造函數(shù)執(zhí)行結(jié)束后,虛函數(shù)表指針才會被正確的初始化
2.析構(gòu)函數(shù)可以成為虛函數(shù)--建議在設(shè)計(jì)類時(shí)將析構(gòu)函數(shù)聲明為虛函數(shù)

Q:構(gòu)造函數(shù)中是否可以發(fā)生多態(tài)?析構(gòu)函數(shù)是否可以發(fā)生多態(tài)?
1.構(gòu)造函數(shù)中不可能發(fā)生多態(tài)行為--在構(gòu)造函數(shù)執(zhí)行時(shí),虛函數(shù)表指針未被正確初始化
2.析構(gòu)函數(shù)在不可能發(fā)生多態(tài)行為--在析構(gòu)函數(shù)執(zhí)行時(shí),虛函數(shù)表指針已經(jīng)被銷毀
C.關(guān)于繼承中的強(qiáng)制類型轉(zhuǎn)換
1.dynamic_cast是與繼承相關(guān)的類型轉(zhuǎn)換關(guān)鍵字,并且要求相關(guān)的類中必須有虛函數(shù)
2.用于直接或者間接繼承關(guān)系的指針之間
C++--被遺棄的多重繼承、經(jīng)典問題
編譯器會檢查dynamic_cast的使用是否正確,類型轉(zhuǎn)換的結(jié)果只可能在運(yùn)行的階段才能得到
代碼示例

#include <iostream>
#include <string>

using namespace std;

class Base
{
public:
    Base()
    {
        cout << "Base::Base()" << endl;
    }

    virtual ~Base()//析構(gòu)虛函數(shù)
    {
        cout << "Base::~Base()" << endl;
    }
};

class Derived : public Base
{

};

int main()
{
    Base* p = new Derived;//指向的是子類對象

    Derived* pd = dynamic_cast<Derived*>(p);//強(qiáng)制轉(zhuǎn)換

    cout<<"pd="<<pd<<endl;

    if( pd != NULL )
    {
        cout << "pd = " << pd << endl;
    }
    else
    {
        cout << "Cast error!" << endl;
    }

    delete p;

    return 0;
}

將其修改之后的打印結(jié)果比較
C++--被遺棄的多重繼承、經(jīng)典問題
C++--被遺棄的多重繼承、經(jīng)典問題C++--被遺棄的多重繼承、經(jīng)典問題
我們可以知道不能將子類指針對象指向父類,產(chǎn)生的對象時(shí)無效的

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI