2011-03-15 224 views
3

是否有無論如何我可以在沒有繼承的情況下訪問類中的受保護變量。C++受保護的訪問

class ClassA{ 
    protected: 
    int varA; 
}; 

class ClassB{ 
    protected: 
    ClassA objectA; 

}; 


ClassB theMainObject; 

我想通過theMainObject訪問varA。

+0

+1好的問題;) – 2011-03-15 13:18:40

回答

0

我假設修改ClassA的定義是被禁止的。

這是給你一個取巧的辦法,但我不鼓勵你使用它:)

class ClassA 
{ 
protected: 
    int varA; 
}; 

class ProtectedRemover // magic thing 
{ 
public: // <- Note this! :) 
    int varA; 
}; 

class ClassB 
{ 
protected: 
    ClassA objectA; 

public: // Just add two methods below 

    int getProtectedVarA() 
    { 
     return reinterpret_cast<ProtectedRemover*>(&objectA)->varA; 
    } 

    void setProtectedVarA(int i) 
    { 
     reinterpret_cast<ProtectedRemover*>(&objectA)->varA = i; 
    } 
}; 

int main() 
{ 
    ClassB theMainObject; 

    // Set protected thing. 
    theMainObject.setProtectedVarA(3); 

    // Get protected thing. 
    std::cout << theMainObject.getProtectedVarA() << std::endl; 
} 

因此,有訪問和修改保護/私有數據的方式。從theMainObject

+2

-1這是未定義的行爲,因爲這些類型與編譯器無關請參閱,特別是如果'ClassA'具有OP沒有顯示給我們的虛擬方法。 – 2011-03-15 13:17:36

+0

問題男人沒有虛擬功能!爲什麼這裏的人們都充滿了願意投票? 我知道你也發佈了一個答案,但仍然不公平:) :) 爲什麼你認爲作者不知道如何添加訪問器到ClassA? :)你的答案應該先下來投票:) – 2011-03-15 13:35:23

+0

+在我的例子中沒有任何未定義的行爲! :) – 2011-03-15 13:45:19

3

有一個存取函數是唯一的方法,即;

public: 
    int getVarA(){return varA;} 
+0

你應該讓'INT getCarA()const'。 – 2011-03-15 13:08:57

+0

不是唯一的辦法,請閱讀我的文章;) – 2011-03-15 13:48:07

+0

你是對的@ Space_C0wb0y,我通常懶得標記常量函數:p – deek0146 2011-03-15 14:36:46

5

你可以做classB朋友classA

class ClassA{ 
    protected: 
    int varA; 

    friend ClassB; 
} 

但使用存取可能會更好,因爲你是不是類耦合在一起。

class ClassA{ 
    int getA() { return varA;} 
    void setA(int a) { varA = a; } 
    protected: 
    int varA; 
} 
1

friend是你friend.Use通過提的,你要訪問的在其中ü要使用類朋友類的關鍵字!

1

你不能,而且很有可能不應該訪問varA直接;
誰在想這是不可能的,投了。 protected與無關類(如您的兩個示例類)的私有相同,因此varA不具有可見性。使用ClassA的正常API來操縱其狀態。

如果varAClassA結果狀態的一部分,你只需要讀取權限,那麼你應該公開訪問添加到類:

public: 
    int getVarA() const 
    { 
     return varA; 
    } 
+1

-1 downvoting我的創造性的答案,因爲你認爲作者不知道如何添加訪問者! :) – 2011-03-15 13:37:57

+0

我同意。但我不打算投下它,因爲我非常感謝幫助。 – user346443 2011-03-15 13:59:24

1

除了使ClassB的ClassA的一個朋友那裏是達到ClassA內部的一些標準和非標準攻擊。你可以閱讀關於他們的Herb Sutter's article

2

添加標準的getter/setter函數:

int ClassA::GetVarA() 
{ 
    return varA; 
} 
BOOL ClassA::SetVarA(int nNewVar) 
{ 
    // Perform verifications on nNewVar... Return FALSE if didn't go well. 

    // We're satisfied. Set varA to the new value. 
    varA = nNewVar; 

    return TRUE; 
} 
0

作爲標記B mentionned,通過Hovhannes Grigoryan的提出的解決方案是不是安全,也許會有意想不到的行爲,因爲ProtectedRemover和CLASSA無關....

我在過去使用這一點,它可能會更安全,我認爲:

class ClassA 
{ 
protected: 
    int varA; 
}; 

class ProtectedRemover : public ClassA // now, they are related! 
{ 
public: // <- Note this! :) 
    int getA() { return varA; } 
    void setA(int a) { varA = a; } 
}; 

class ClassB 
{ 
protected: 
    ClassA objectA; 

public: // Just add two methods below 

    int getProtectedVarA() 
    { 
     return ((ProtectedRemover)*(&objectA))->getA(); 
    } 

    void setProtectedVarA(int i) 
    { 
     ((ProtectedRemover)*(&objectA))->setA(i); 
    } 
}; 

注意它提出萬無一失得到待定的行爲....但可以爲L而不是原來的解決方案,其中ProtectedRemover和classA是無關的......並且如果ClassA具有屬性的音調也更容易做到!

除非你真的沒有別的選擇,否則還是不推薦的(不能通過讓你的班級朋友或添加settre/getter來修改classA)!

沒有真的不可能....