問題(知識點)描述:
a. 在C++的類的成員函數中,允許直接訪問該類的對象的私有成員變量。
b. 在類的成員函數中可以訪問同類型實例的私有變量。
c. 拷貝構造函數裏,可以直接訪問另外一個同類對象(引用)的私有成員。
d. 類的成員函數可以直接訪問作爲其參數的同類型對象的私有成員。
舉例描述上述知識:
1).在拷貝構造函數中可以訪問引用對象的私有變量:例如:
class Point
{
public:
Point(int xx=0,int yy=0){X=xx;Y=yy;}
Point(Point &p);
private:
int X,Y;
};
Point::Point (Point &p)
{
X=p.X;
Y=p.Y;
}
2). 在類的成員函數中可以訪問同類型實例的私有變量
class A
{
public:
int getA() const { return a; }
voidsetA(int val) { a = val; }
voidassign(A& _AA)
{
this->a = _AA.a;
_ AA.a= 10; //可以直接訪問
}
voiddisplay()
{
cout<<"a:"<<a<<endl;
}
private:
int a;
};
3).
#include<iostream>
using namespace std;
classTestClass
{
public:
TestClass(int amount)
{
this->_amount = amount;
}
void UsePrivateMember()
{
cout<<"amount:"<<this->_amount<<endl;
/*----------------------*/
TestClass objTc(10);
objTc._amount = 15; //訪問同類型實例的私有變量
cout<<objTc._amount<<endl;
/*----------------------*/
}
private:
int _amount;
};
int main()
{
TestClass tc(5);
tc.UsePrivateMember();
return(0);
}
關於該問題(知識點)的討論和或解釋:
1. 私有是爲了實現“對外”的信息隱藏,或者說保護,在類自己內部,有必要禁止私有變量的直接訪問嗎?難道還要讓我們聲明一個類爲自身的友元?
Point::Point(Point &p)
{
X=p.X; //這在Point類中的Point函數內,所以沒錯。
Y=p.Y;
}
請記住你是在定義你的類,不是在用。
2. C++的訪問修飾符的作用是以類爲單位,而不是以對象爲單位。
通俗的講,同類的對象間可以“互相訪問”對方的數據成員,只不過訪問途徑不是直接訪問.
步驟是:通過一個對象調用其public成員函數,此成員函數可以訪問到自己的或者同類其他對象的public/private/protected數據成員和成員函數(類的所有對象共用),而且還需要指明是哪個對象的數據成員(調用函數的對象自己的成員不用指明,因爲有this指針;其他對象的數據成員可以通過引用或指針間接指明)
可以提供訪問行爲的主語爲“函數”。
類體內的訪問沒有訪問限制一說,即private函數可以訪問public/protected/private成員函數或數據成員,同理,protected函數,public函數也可以任意訪問該類體中定義的成員public繼承下,基類中的public和protected成員繼承爲該子類的public和protected成員(成員函數或數據成員),然後訪問仍然按類內的無限制訪問。
3. 注意公有和私有的概念:每個類的對象都有自己的存貯空間,用於存儲內部變量和類成員;但同一個類的所有對象共享一組類方法,即每種方法只有一個源本。很明顯,類方法是所有該類對象共同使用的,因此不存在每個對象有一組類方法的副本。源本的類方法自然可以訪問所有該類對象的私有成員。
4. 訪問權限是相對於類而言,而非對象!
一個問題,爲什麼成員函數可以訪問私有成員呢?結果很顯然,如果不能訪問,那麼私有成員的存在就沒有了意義。而對於成員函數中允許訪問對象的數據成員,一方面保證了安全性與封裝性,另一方面提供方便的操作。第一句話的解釋,就是承認只有成員函數可以訪問私有成員,這裏不涉及友元及派生。這樣一來,安全性仍然得到了保證,也完成了封裝工作。對於第二句話,試想,如果都得靠接口來實現數據傳送,那麼操作是否極爲不便?既然處於成員函數中,已經保證了足夠的安全和封裝性,那麼這裏如果還得藉助接口,就有些不合情合理了。作爲對數據成員的靈活處理,設計者允許在成員函數中訪問對象的私有成員,爲使用者提供了很大的方便。這同時也反映了語言的靈活性和原則性.
C++中類訪問權限控制:
第一:private, public, protected 訪問標號的訪問範圍,在沒有繼承的情況下:
private:
只能由1.該類中的函數、2.其友元函數訪問。
不能被任何其他訪問,該類的對象也不能訪問。
protected:
可以被1.該類中的函數、2.子類的函數、以及3.其友元函數訪問。
但不能被該類的對象訪問。
public:
可以被1.該類中的函數、2.子類的函數、3.其友元函數訪問,也可以由4.該類的對象訪問。
注:友元函數包括3種:設爲友元的普通的非成員函數;設爲友元的其他類的成員函數;設爲友元類中的所有成員函數。
第二:類的繼承後方法屬性變化,具體情況如下:
private 屬性是不能夠被繼承的,protected繼承和private繼承能降低訪問權限。
使用private繼承,父類的protected和public屬性在子類中變爲private;
使用protected繼承,父類的protected和public屬性在子類中變爲protected;
使用public繼承,父類中的protected和public屬性不發生改變;
如下所示:
public: protected: private:
public繼承 public protected
不可用
protected繼承 protected protected
不可用
private繼承 private private 不可用
class A
{
public:
A(int i) : a(i){}
protected:
int a;
};
class B : public A
{
public:
B(int i) : A(i) {}
void fb(A &a) {cout<<a.a<<endl;}
};
編譯出錯;若將倒數第二行改爲
voidfb(B &a){cout<<a.a<<endl;}
則編譯運行都沒問題:
保護類型只能被本類中的方法或者派生類訪問,不能被本類的具體對象訪問。a是類A的保護類型成員,能被A中的方法(函數)訪問,能被B類訪問,不能被類A的具體對象A a訪問。
一個類的保護成員或私有成員只能被該類的成員函數或該類的友元函數來訪問,外部代碼不能訪問,B類中的函數fb對於A類中的保護成員變量a來說是外部代碼不能通過該類的對象直接訪問,由於B類公有繼承了A類,a在A類中是保護成員,則在B類中也是保護成員,因此B類中的函數可以訪問自己的保護成員。