2016-04-26 110 views
1

請考慮以下情況:C++派生的基類朋友函數訪問私人家長?

class A 
    { 
    friend void B::Itemfunction(); 
    private: 
    int number; 
    int size; 
    public: 
    Randomfunction(); 
    } 

    class B : public A 
    { 
    private: 
    string Random; 
    public: 
    void Itemfunction(); 
    void CheckLog(); 

    } 

難道在Itemfunction由A型的訪問obj的私有數據成員的對象是可能的嗎?如:

void B::Itemfunction(){ 
    A obj; 
    //Possible to do... 
    obj.number = 2; 
    } 

據我所知,派生類B可訪問的所有公共部分,但如果我想只是一個功能(Itemfunction)訪問私處會變成這樣做的正確方法?我只想看看我的理解是否正確。

乾杯

回答

1

在你的代碼,在那裏你實現Itemfunction,要創建本地A類型的新的,完全不相關的對象。在繼承中,您的B對象具有A類型的內部子對象。您可以直接在B內訪問A的字段。但是,您無法訪問私人會員。你的友誼把戲不會奏效;除非定義B的定義,否則不能定義B的方法,但在定義A之前不能定義B,正如您所看到的,我們正在進行循環。你可以做的是,使該成員保護:

class A 
{ 
    protected: 
    int number; 
    private: 
    int size; 
    public: 
    Randomfunction(); 
} 

void B::Itemfunction() { 
    number = 2; 
} 
+0

謝謝你的迴應,我現在看到圈子的問題。我想除了你所描述的解決方案之外,讓B班成爲A的朋友也應該是正確的?或者作爲派生類和朋友會有問題嗎? –

+0

想想你的程序的需求。如果'A'朋友'B'使得'B'可以訪問,那麼孩子'C'或'D'是什麼?當你添加子類時友誼不會擴展。 ['protected'access will](http://en.cppreference.com/w/cpp/language/access),如果這是你想要的。 – user4581301

+0

@ afc_1995'protected'旨在解決這個確切的問題,所以你應該真的使用'protected'。如果'B'是'A'的朋友,它就可以訪問所有內容,包括私人成員。保護性和私密性的全部要點是,A可以決定其子女有權訪問的內容。你有什麼理由選擇友誼來保護自己? –

1

不,這是不可能的。你不能爲尚未完全聲明的類朋友使用類成員函數。

在這種情況下,唯一的方法(因爲class B需要一個徹底宣告class A繼承),是轉發聲明class B;和朋友全班:

#include <iostream> 
#include <string> 

    class B; 

    class A 
    { 
    // friend void B::Itemfunction(); 
    friend class B; 
    private: 
    int number; 
    int size; 
    public: 
    void Randomfunction(); 
    }; 

    class B : public A 
    { 
    private: 
    std::string Random; 
    public: 
    void Itemfunction(); 
    void CheckLog(); 

    }; 

int main() 
{ 
} 

Live Demo

+0

非常感謝您的明確解釋!非常感謝 - 我可能不得不讓B成爲A的朋友,因爲這樣做似乎....沒有意識到需要轉發宣言 - 偉大的提示! –

+0

然後,最好讓該成員保護而不是私人,而不是讓整個班級的朋友。 – Slava

+0

@Slava當然,好點。 –

0

這有雞雞蛋問題。 B必須完全定義爲A才能看到B::Itemfunction

class A 
{ 
    friend void B::Itemfunction(); <-- Itemfunction does not exist yet 
private: 
    int number; 
    int size; 
public: 
    int Randomfunction(); 
}; 

class B: public A 
{ 
private: 
    std::string Random; 
public: 
    void Itemfunction(); 
    void CheckLog(); 

}; 

交換順序將無法工作或者是因爲B需要A被定義爲從A繼承。

class B: public A <-- A does not exist yet 
{ 
private: 
    std::string Random; 
public: 
    void Itemfunction(); 
    void CheckLog(); 

}; 

class A 
{ 
    friend void B::Itemfunction(); 
private: 
    int number; 
    int size; 
public: 
    int Randomfunction(); 
}; 

方案1向前定義class B所以編譯器知道b存在,即使對此一無所知,然後friend全班同學,因爲A只知道B存在。 OP的friend關係得以維持。

class B; <-- forward definition of B 
class A 
{ 
    friend class B; <-- friending all of B, not just the function 
private: 
    int number; 
    int size; 
public: 
    int Randomfunction(); 
}; 

class B: public A 
{ 
private: 
    std::string Random; 
public: 
    void Itemfunction(); 
    void CheckLog(); 

}; 

但是!全部B現在可以完全訪問所有A。如果A想要保留size或其他任何隱藏在其控制之下的成員,則很難。 B可以調用A的所有函數並更改所有A的成員變量。 B完全可以播放A

這也不會擴展到其他的子類。B可以看到所有的A,但是CD不能。

所以說你有一個不太重要的例子,其中A不允許任何人混淆size的值。也許這是內部陣列的容量,並且更改size將導致A運行超過分配的內存末尾。原因在這裏並不重要;爲了本示例的目的,除A外,沒有人可以更改size

這導致我們找到解決方案2:protected access和訪問器函數。

class A 
{ 
protected: <-- all inheritors can access members in this block. No one else can 
    int number; 
private: <-- only A can access members in this block 
    int size; 
public: 
    int Randomfunction(); 
    int getSize() <-- accessor function to provide read-only access to size 
    { 
     return size; 
    } 
}; 

class B: public A 
{ 
private: 
    std::string Random; 
public: 
    void Itemfunction(); <-- can do anything to number and read size 
    void CheckLog(); <-- so can this 

}; 

class C: public A 
{ 
private: 
    std::string member; 
public: 
    void doStuff(); <-- and this 
    void DoOtherStuff(); <-- and this 

}; 

BC可以訪問A::number,並可以使用A::getSize看到size值。 number可以更改BC,但size不能。如果您擔心調用函數的代價爲size,請不要這樣做。當編譯器完成A::getSize時,你甚至不會知道它在那裏。它可能不是。

相關問題