您好,登錄后才能下訂單哦!
Q:C++中是否允許一個(gè)類繼承自多個(gè)父類?
在實(shí)際的C++編譯環(huán)境中,C++是支持編寫多重繼承的代碼
1.一個(gè)子類可以擁有多個(gè)父類
2.子類擁有所有父類的成員變量
3.子類繼承所有父類的成員函數(shù)
4.子類對象可以當(dāng)作任意父類對象使用
多重繼承的語法規(guī)則
但是在多重繼承中會存在許多問題
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é)果
我們可以看到在條件判斷語句中,paa與pbb指向的是同一個(gè)對象,按理說應(yīng)該打印相同時(shí)的語句,可是卻打印錯(cuò)誤,從接下來的地址打印結(jié)果是不一樣的,這就造成了多重繼承的問題--同一個(gè)對象取地址之后進(jìn)行初始化,但是pa與pb打印的結(jié)果卻不同
Q:多重繼承可能產(chǎn)生冗余的成員
代碼實(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;
}
由運(yùn)行結(jié)果可以知道,在進(jìn)行print時(shí)出錯(cuò),這是因?yàn)镈octor由于繼承,會有兩個(gè)打印的函數(shù),所以通過作用域分辨符進(jìn)行改正
由于冗余,打印的結(jié)果可能不一樣
當(dāng)多重繼承關(guān)系出現(xiàn)閉合時(shí)將產(chǎn)生暑假冗余的問題
解決方案:虛繼承
一.關(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é)果
關(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)系的指針之間
編譯器會檢查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é)果比較
我們可以知道不能將子類指針對象指向父類,產(chǎn)生的對象時(shí)無效的
免責(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)容。