文章標題

一、友元的不可繼承
/***************************************/
class B;//B的向前聲明

class A
{
friend B;//若之前即無B的定義,又無其聲明,則此處報錯
protected:
int _i;
};

class B
{
public:
void foo()
{
_a._i=0;//可訪問
}
protected:
A _a;
};

//正確:
//根據類A中定義,類B爲類A的友元,所以類B可以直接訪問類A的保護型成員。
/***************************************/

/***************************************/
class BC : public B
{
public:
void bar()
{
_a._i=1;//不可訪問,編譯出錯
}
};
//錯誤:
//類B爲類A的友元,但B的子類將不會繼承友元關係,所以類BC不可直接訪問類A的保護型成員。
//當一個類是另一個的類的友元類時,該友元類的子類不是這個類的友元
/***************************************/

/***************************************/
class B;//B的向前聲明
class BC;//BC的向前聲明
class A
{
friend B;
friend BC;//之前不要忘記BC的聲明
protected:
int _i;
};
//正確:
//修改之後,類B、BC均可直接訪問類A的保護型成員。
/***************************************/

二、友元的“可繼承”
/***************************************/

include

class B
{
friend class A;
private:
virtual void Print() const {
std::cout << “B” << std::endl;
}
};

class D: public B
{
private:
virtual void Print() const {
std::cout << “D” << std::endl;
}
};

class A
{
public:
A() {
B b;
std::cout << “A Constructor: “;
b.Print(); // ok
//D d;
//d.Print(); // error: ‘virtual void D::Print() const’ is private
}

  void Print(const B &b) const {
      std::cout << "A --> ";
      b.Print();
  }

};

int main()
{
A a;
B b;
D d;

  a.Print(b);
  a.Print(d);

}
/***************************************/
在上面的代碼中,被註釋了的部分不能夠通過編譯,因爲D不是A的友元類,B的友元關係並沒有被繼承。而在A的Print函數成員中,參數爲基類B的const引用;而實參卻可以是D類的對象,從而實現了在A類中調用D類成員的目的。當然,你完全可以把A聲明爲D的友元類。但是,這時主要想說明一個問題,那就是,有了虛機制,可以“繼承”這種友元關係。
對這種機制的解釋:首先,在A的Print函數中,通過B類對象調用其私有的虛函數(b.Print();),由於A是B的友元,該調用是完全合法的。而在用D對象調用A的Print函數時時,b.Print()調用動態綁定到了對D類對象的函數版本的調用。
這裏,也說明了另外一個問題:類成員的訪問控制只是在編譯時有效

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章