您好,登錄后才能下訂單哦!
Q:C++中是否允許一個類繼承自多個父類?
在實際的C++編譯環境中,C++是支持編寫多重繼承的代碼
1.一個子類可以擁有多個父類
2.子類擁有所有父類的成員變量
3.子類繼承所有父類的成員函數
4.子類對象可以當作任意父類對象使用
多重繼承的語法規則
但是在多重繼承中會存在許多問題
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//擁有兩個父類
{
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;
//兩個父類指針指向同一個對象
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;
}
運行結果
我們可以看到在條件判斷語句中,paa與pbb指向的是同一個對象,按理說應該打印相同時的語句,可是卻打印錯誤,從接下來的地址打印結果是不一樣的,這就造成了多重繼承的問題--同一個對象取地址之后進行初始化,但是pa與pb打印的結果卻不同
Q:多重繼承可能產生冗余的成員
代碼實現
#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;
}
由運行結果可以知道,在進行print時出錯,這是因為Doctor由于繼承,會有兩個打印的函數,所以通過作用域分辨符進行改正
由于冗余,打印的結果可能不一樣
當多重繼承關系出現閉合時將產生暑假冗余的問題
解決方案:虛繼承
一.關于動態內存分配
Q:new和malloc的區別?delete和free的區別?
A.new關鍵字與malloc函數的區別
1.new關鍵字是C++的一部分,malloc是由C庫提供的函數
2.new以具體類型為單位進行內存分配,malloc以字節為單位進行內存分配
3.new在申請內存空間時可進行初始化,malloc僅根據需要申請定量的內存空間
代碼示例
#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;
}
運行結果
關于動態內存分配
new和malloc的區別
1.new在所有C++編譯器中都能被支持,malloc在某些系統開發中是不能調用的
2.new能夠觸發析構函數的調用,malloc僅分配需要的內存空間
3.對象的創建只能使用new,malloc不適合面向對象開發
delete和free的區別
1.delete在所有C++編譯器中都被支持,free在某些系統開發中是不能調用的
2.delete能夠觸發析構函數的調用,free僅歸還之前的分配空間
3.對象的銷毀只能使用delete,free不適合面向對象的開發
B.關于虛函數
Q:構造函數是否可以成為虛函數?析構函數是否可以成為虛函數?
1.構造函數不可能成為虛函數--在構造函數執行結束后,虛函數表指針才會被正確的初始化
2.析構函數可以成為虛函數--建議在設計類時將析構函數聲明為虛函數
Q:構造函數中是否可以發生多態?析構函數是否可以發生多態?
1.構造函數中不可能發生多態行為--在構造函數執行時,虛函數表指針未被正確初始化
2.析構函數在不可能發生多態行為--在析構函數執行時,虛函數表指針已經被銷毀
C.關于繼承中的強制類型轉換
1.dynamic_cast是與繼承相關的類型轉換關鍵字,并且要求相關的類中必須有虛函數
2.用于直接或者間接繼承關系的指針之間
編譯器會檢查dynamic_cast的使用是否正確,類型轉換的結果只可能在運行的階段才能得到
代碼示例
#include <iostream>
#include <string>
using namespace std;
class Base
{
public:
Base()
{
cout << "Base::Base()" << endl;
}
virtual ~Base()//析構虛函數
{
cout << "Base::~Base()" << endl;
}
};
class Derived : public Base
{
};
int main()
{
Base* p = new Derived;//指向的是子類對象
Derived* pd = dynamic_cast<Derived*>(p);//強制轉換
cout<<"pd="<<pd<<endl;
if( pd != NULL )
{
cout << "pd = " << pd << endl;
}
else
{
cout << "Cast error!" << endl;
}
delete p;
return 0;
}
將其修改之后的打印結果比較
我們可以知道不能將子類指針對象指向父類,產生的對象時無效的
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。