1. 程式人生 > >繼承、多型

繼承、多型

常用的繼承有三種:公有繼承、保護繼承、私有繼承

公有繼承

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 基類名