c++繼承方式


c++繼承方式

    派生類繼承了基類中除了構造和析構函數外所有部分,並且基類成員在子類中訪問屬性取決於繼承方式。c++類中的成員函數和變量有三種繼承方式,分別為:公有繼承(public),私有繼承(private)和保護繼承(protect)。

    public:用該關鍵字修飾的成員表示公有成員,該成員不僅可以在類內可以被訪問,在類外也是可以被訪問的,是類對外提供的可訪問接口;
    private:用該關鍵字修飾的成員表示私有成員,該成員僅在類內可以被訪問,在類體外是隱藏狀態;

    protected:用該關鍵字修飾的成員表示保護成員,保護成員在類體外同樣是隱藏狀態,但是對於該類的派生類來說,相當於公有成員,在派生類中可以被訪問。

一、公有繼承(public)

    公有繼承時,基類的公有成員和保護成員在派生類中屬性不變,但私有成員不可直接訪問。基類成員對派生類對象的可見性為:基類的公有成員可見,保護成員和私有成員不可見,即通過派生類的對象只能訪問基類的public成員。
    所以,在公有繼承時,派生類的對象可以直接訪問基類中的公有成員,派生類的成員函數可以直接訪問基類中的公有成員和保護成員。

#include<iostream>

using namespace std;

class point{

private: int x, y;

public:

void initpoint(float x1 = 0, float y1 = 0) {

	x = x1;
	y = y1;
}

void move(float xx=0, float yy=0) {

	x += xx;
	y += yy;

}

float getx() const{
	return x;
}

float gety() const {
	return y;
}

};

class Rectangle :public point {   //公有繼承

private:

int w, h;

public:
void initRectangle(float x, float y, float w, float h) {

	initpoint(x, y);

	this->w = w;
	this->h = h;
}

float geth() const {
	return h;
}

float getw() const {
	return w;

}
};

int main() {

Rectangle rect;

rect.initRectangle(2, 3, 20, 30);

rect.move(3, 2);

cout << rect.getx() << endl;
cout << rect.gety() << endl;
cout << rect.getw() << endl;
cout << rect.geth() << endl;

return 0;
}

    我們可以看出,在初始化時,由於不能直接初始化基類私有成員,我們直接調用了initpoint這個函數接口。這個函數是基類中的,由於是public方式直接可以使用此基類成員函數。

一、私有繼承(public)

    當繼承方式為私有繼承時,基類的公有成員和保護成員都以私有成員出現在派生類中,同樣私有成員在派生類中不可直接訪問。此時派生類成員函數可以調用基類公有成員和保護成員,但是在類外部不可使用任何基類成員。可以看出,再進一步派生的話,基類所有成員就無法被直接訪問。一般私有繼承的使用比較少。

#include<iostream>

using namespace std;

class point {

private: int x, y;

public:

void initpoint(float x1 = 0, float y1 = 0) {

	x = x1;
	y = y1;
}

void move(float xx = 0, float yy = 0) {

	x += xx;
	y += yy;

}

float getx() const {
	return x;
}

float gety() const {
	return y;
}

};

class Rectangle :private point {   //私有繼承

private:

int w, h;

public:
void initRectangle(float x, float y, float w, float h) {

	initpoint(x, y);

	this->w = w;
	this->h = h;
}

float getx() const {
	return point::getx();
}

float gety() const {
return point::gety();
}


float geth() const {
	return h;
}

float getw() const {
	return w;

}

void move(float offx, float offy) {

	point::move(offx, offy);
}
};

int main() {

Rectangle rect;

rect.initRectangle(2, 3, 20, 30);

rect.move(1, 1);

cout << rect.getx() << endl;
cout << rect.gety() << endl;
cout << rect.getw() << endl;
cout << rect.geth() << endl;

return 0;
}

    需要注意的是,私有繼承后基類成員函數只能在派生類函數中使用,在外部引用會報錯。如派生類直接調用move函數時就會報錯。為了保證派生類繼續擁有基類的接口,就需要重新聲明相同的成員例如上例重新聲明了getx(),gety(),和move()函數,根據基類隱藏原則基類函數被隱藏,但實現的是相同的效果。

三.保護繼承

    在保護繼承中,基類公有成員和保護成員都以保護成員出現在派生類中,但基類私有成員仍然不能被直接訪問。保護在派生類中被視為公有成員,在類外被視為私有成員。他結合了公有成員和私有成員的優點,更合理地保護成員。私有繼承和保護繼承的區別中。所有成員的訪問屬性都完全相同,但是如果派生類繼續派生,保護繼承下的基類成員一直都存在派生類基類中,但是私有成員將無法訪問基類成員。
    保護繼承既實現成員隱蔽,又方便繼承。

    來看一個錯誤例子。

#include<iostream>

using namespace std;

class A {

protected:

int x;

};


int main() {

A a;

a.x = 1;

return 0;
}

    我們看出他會報錯。

    在沒有派生類的情況下,保護類型和私有類型相似,他們都不能在類外訪問,否則會報錯。但是如果A類以公有派生產生了B類,則在B類中,A中的保護成員像公有成員一樣可以直接調用。

#include<iostream>

using namespace std;

class A {

protected:
int x;

};

class B:public A{

public:

	void fuc(){

	x = 5;

cout << x;
}

};


int main() {

B b;

b.fuc();

return 0;
}

    需要注意的是,如果B是A的派生,B中的成員函數只能通過B的對象訪問A中定義的protected成員,而不能通過A的對象訪問A中的protected成員。

    三中繼承方式總結為下圖:


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM