OOP 3大特性: 資料抽象,繼承,動态綁定 3中通路标号 protected, public, private 對比
用 類進行資料抽象;用繼承類繼承基類的成員,實作繼承;通過将基類相應函數聲明為virtual,是編譯器在運作時決定調用基類函數or派生類函數 完成 動态綁定,即表現 多态性。 多态性:利用繼承和動态綁定,通過基類指針和引用來表現。 動态綁定兩個條件:1. 虛函數,2. 指針或引用
class Item_book
{
private :
std : :string isdn;
protected :
double price;
public :
std : :string book() const { return isdn; }
};
class Bulk_item : : public Item_book
{
...
};
void Bulk_item : :memfcn( const Bulk_item &d, const Item_base &b)
{
cout <<isdn; // error: no access to isdn which is private member in Item_base (1)
double ret = price; //ok: use this->price (2)
ret = d.price; // ok: use price from a Bulk_item object (3)
ret = b.price; // error: no access to price from an Item_base (4)
}
# include <iostream >
using namespace std;
class Base
{
private :
int age;
protected :
int num;
public : Base() { num = 5; } void set_num( const Base& a)
{
cout <<a.num <<endl;
}
virtual void show()
{
num = 1;
cout <<num <<endl;
}
};
class Devi : public Base
{
public :
void show()
{
num = 2;
cout <<num <<endl;
}
void test( const Base &a, const Devi &b)
{
cout <<b.num <<endl; //(5)
}
};
int main()
{
Base b, a;
Devi d; b.set_num(a); (7)
b.show();
d.show(); //ok protected num可被子類使用
d.test(b, d);
//cout<<d.num; //error protected num 不可被子類 對象使用 (6)
return 0;
} 區分(5)(6)的差別,一個在 類的成員函數定義中(可以通過 類對象調用其保護成員,如公有成員一樣),一個在 類定義外部
總結: 通路控制與繼承: public: private: 隻能被基類的成員和友元函數通路。不能被類的對象通路。同時不能被派生類(的成員函數)通路。如下 (1)。 protected:可以被派生類(的成員 (2))通路。不可以被派生類對象通路 (6) 。 例外: ( 例外 :在 派生類内部 可以通過派生類對象通路其基類的protected)如下(3),同時 對比下圖(5)和(6); 但不能被基類的對象通路(對于基類,相當于基類的private)如下(4);基類在基類内部可以通過基類對象通路其protected成員(7) 即 派生類可以通路基類 protected 和 public 中的成員。
公有、私有、保護繼承 對類所繼承的成員的通路由 基類的成員通路級别和派生類 派生清單中使用的 通路标号 共同控制。 派生類可以 進一步限制,但不能放松對繼承的成員通路。
派生類中的通路級别(3種繼承方式): public:基類成員保持自己的通路級别:基類的public->派生類的public,基類的protected -> 派生類的protected。 protected:基類的public和protected成員在派生類中為proteced成員 private:基類的所有成員在派生類中為private成員。
class Base
{
public :
void basemen();
protected :
int i;
private :
std : :string isdn;
....
};
class Public_derived : public Base
{
int use_base() { return i; } //ok: as proteced member in Public_derived
//...
};
class Private_derived : private Base //注意,對比下面
{
int use_base() { return i;} // ok: i is protected member in Base, private member in Pivate_derived
int print_isdn() {cout <<isdn; } //error: isdn is private member in Base
};
派生通路标号 還控制來自非直接派生類的通路:
class Derived_from_Private : public Private_derived
{
//error: Base::i is private in Private_derived
int use_base() { return i;}
};
class Derived_from_Private : public Public_derived
{
//ok: Base::i remain proteced in Public_derived
int use_base() { return i;}
}
struct VS class struct 定義的類 預設範圍級别為public類型,定義的派生類 預設具有public繼承 class 定義的類 預設範圍級别為 private類型,定義的派生類 預設具有 private繼承
轉換與繼承 可以将 派生類轉換為基類---通過初始化或複制。 一般調用基類的複制構造函數或指派函數。 例:
Item_base item; //object of base type
Bulk_item bulk; //object of derived type
//ok:use Item_base::Item_base(const Item_base&) constructor
Item_base item(bulk); // bulk is "slice down" to its Item_base portion
//ok:use Item_base::operator = (const Item_base&)
item = bulk; // bulk is "slice down" to its Item_base portion
基類 不能 自動 轉換為 派生類,否則派生類會通路 不存在的成員 (基類不存在的成員), 除非在 知道 基類向派生類轉換為 安全時,可以使用 static_cast強制編譯器進行轉換。或是 用 dynamic_cast 申請在運作時進行檢測。
參照 《C++ primer》 第15章