繼承、多型
常用的繼承有三種:公有繼承、保護繼承、私有繼承
公有繼承
1 運用protected宣告類的屬性時,只允許友元類和派生類訪問它,禁止在類外部通過例項物件訪問。
下面用一個例子解釋公有繼承的應用以及protected訪問限定符的作用
#include "stdafx.h" #include "iostream" #include "string" using namespace std; class fish { protected : bool Freshwaterproperty; public: void swim() { if (Freshwaterproperty == true) cout << "the fish is in lake " << endl; else cout << "the fish is in sea" << endl; } }; class seafish:public fish { public: seafish() { Freshwaterproperty =true; } }; class lakefish :public fish { public: lakefish() { Freshwaterproperty =false; } }; int main() { seafish lunch; lunch.swim(); lakefish dinner; dinner.swim(); return 0; }
2 基類的初始化——向基類傳遞引數
運用基類的初始化,在宣告派生類時,直接賦予引數。
包含初始化列表的派生類函式建構函式
#include "stdafx.h" #include "iostream" #include "string" using namespace std; class fish { protected : bool Freshwaterproperty; public: fish(bool intFreshwaterproperty):Freshwaterproperty(intFreshwaterproperty) {}; void swim() { if (Freshwaterproperty == true) cout << "the fish is in lake " << endl; else cout << "the fish is in sea" << endl; } }; class seafish:public fish { public: seafish():fish(true) { } }; class lakefish :public fish { public: lakefish():fish(false) { } }; int main() { seafish lunch; lunch.swim(); lakefish dinner; dinner.swim(); return 0; }
3 派生類覆蓋基類函式及處理方法
#include "stdafx.h" #include "iostream" #include "string" using namespace std; class fish { protected : bool Freshwaterproperty; public: fish(bool intFreshwaterproperty) :Freshwaterproperty(intFreshwaterproperty) {}; void swim() { if (Freshwaterproperty == true) cout << "the fish is in lake " << endl; else cout << "the fish is in sea" << endl; } }; class seafish:public fish { public: seafish():fish(true) { } void swim() { cout << "the seafish is fast " << endl; } }; class lakefish :public fish { public: lakefish():fish(false) { } void swim() { cout << "the lakefish is slow " << endl; } }; int main() { seafish lunch; lunch.swim(); lakefish dinner; dinner.swim(); return 0; }
輸出結果為派生類的方法,將基類方法覆蓋:
解決方法:
1在派生類方法裡面呼叫積累函式
//上面的例子的變化之處
class lakefish :public fish
{
public:
lakefish():fish(false)
{
}
void swim()
{
fish::swim();
cout << "the lakefish is slow " << endl;
}
};
2在主調函式中運用例項化物件訪問時後面運用作用域符訪問
int main()
{
seafish lunch;
lunch.swim();
lakefish dinner;
dinner.fish::swim();
return 0;
}
私有繼承
私有繼承與公有繼承的不同之處:
1 在宣告派生類時運用class seafish:private fish
2 運用私有繼承後,其他seafish的派生類不能訪問基類的成員,要想訪問基類的成員,需要另外宣告一個公有繼承的類。更不能在類外部運用例項化物件對基類的成員(屬性及方法)進行訪問。
3 基類的成員只能在派生類聲明裡訪問
4 一般情況下,儘量不使用私有繼承,必要時,更好選擇是將基類物件作為派生類的私有成員
#include "stdafx.h"
#include "iostream"
#include "string"
using namespace std;
class fish
{
protected :
bool Freshwaterproperty;
public:
fish(bool intFreshwaterproperty) :Freshwaterproperty(intFreshwaterproperty)
{};
void swim()
{
if (Freshwaterproperty == true)
cout << "the fish is in lake " << endl;
else
cout << "the fish is in sea" << endl;
}
};
class seafish:private fish
{
public:
seafish():fish(true)
{
}
void swim2()
{
cout << "the seafish is fast " << endl;
fish::swim();
}
};
class lakefish :public fish
{
public:
lakefish():fish(false)
{
}
void swim()
{
cout << "the lakefish is slow " << endl;
}
};
int main()
{
seafish lunch;
lunch.swim2();
lakefish dinner;
dinner.swim();
dinner.fish::swim();
return 0;
}
保護繼承
保護繼承與私有繼承的不用之處在於:保護繼承派生類的派生類可以訪問基類。
多繼承
class bird :public A,public B ,…
多型
1 使用虛擬函式實現多型行為
多型:運用函式引數呼叫類的方法時,將派生類物件視為基類物件,並執行派生的函式,無需關心引用指向的是那樣一個類。
實現多型重要的一點是:在訪問的基類函式前面新增virtual
#include "stdafx.h"
#include "iostream"
#include "string"
using namespace std;
class fish
{
protected :
bool Freshwaterproperty;
public:
fish(bool intFreshwaterproperty) :Freshwaterproperty(intFreshwaterproperty)
{};
virtual void swim()
{
if (Freshwaterproperty == true)
cout << "the fish is in lake " << endl;
else
cout << "the fish is in sea" << endl;
}
};
class seafish:public fish
{
public:
seafish():fish(true)
{
}
void swim()
{
cout << "the seafish is fast " << endl;
}
};
class lakefish :public fish
{
public:
lakefish():fish(false)
{
}
void swim()
{
cout << "the lakefish is slow " << endl;
}
};
void fishfuntion(fish& inputfishclass)
{
inputfishclass.swim();
};
int main()
{
seafish lunch;
fishfuntion(lunch);
lakefish dinner;
fishfuntion(dinner);
return 0;
}
輸出結果如下:
2 純虛擬函式——抽象基類
1 即與1的類似,在virtual void swim=0;即指定了派生類的方法及特徵
2 抽象基類要求派生類必須對其方法swim進行定義,
#include "stdafx.h"
#include "iostream"
#include "string"
using namespace std;
class fish
{
protected :
bool Freshwaterproperty;
public:
fish(bool intFreshwaterproperty) :Freshwaterproperty(intFreshwaterproperty)
{}
virtual void swim() = 0;
};
class seafish:public fish
{
public:
seafish():fish(true)
{
}
void swim()
{
cout << "the fish is in sea " << endl;
cout << "the seafish is fast " << endl;
}
};
class lakefish :public fish
{
public:
lakefish():fish(false)
{
}
void swim()
{
cout << "the fish is in lake " << endl;
cout << "the lake fish is slow " << endl;
}
};
void fishfuntion(fish& inputfishclass)
{
inputfishclass.swim();
};
int main()
{
seafish lunch;
fishfuntion(lunch);
lakefish dinner;
fishfuntion(dinner);
return 0;
}
3使用虛擬函式釋放記憶體
當類裡面含有解構函式時,將解構函式表示為虛擬函式 virtual ~Base();確保當以基類作為函式的指標時,釋放派生類的記憶體。防止資源為釋放,記憶體洩漏問題。
4 運用虛繼承解決菱形問題
在實現多繼承時,為多繼承的基類又來同一個基類,此時在用例項化物件訪問基類的成員時,將產生二義性,即菱形問題。
解決的方法時在多繼承的每一個類,在繼承同一個基類時, public virtul 基類名