2012-12-26 86 views
10

我用兩個get方法創建了一個類,一個是const,一個是非const。 const方法是公開的,所以用戶可以查詢矢量。非const方法受到保護,所以我可以使用它來修改我需要的數據。爲什麼在const方法爲public並且非const類型被保護時,C++不會強制轉換爲const?

但是,當我嘗試使用該類,並調用get方法時,編譯器會抱怨非const方法受到保護。相反,我必須使用const_cast將對象強制轉換爲const,所以我可以使用公共方法。

有沒有辦法解決這個問題?爲什麼編譯器不會自己創建,因爲有一個公共方法?如果我刪除受保護的版本並保留常量,那麼它可以正常工作,因此它在這種情況下可以執行演員。強制轉換爲const始終是安全的。它消除了常見問題。

回答

3

編譯器在之後考慮可訪問性它決定它想調用哪個成員函數。即,受保護和私有功能仍然可見可見,即使它們不是可訪問

爲什麼?其中一個原因是,如果您通過重載解析忽略了無法訪問的函數,則只需更改其可訪問性即可更改所調用的函數。按照目前的規則,只能導致編譯代碼無法編譯,或者導致目前無法編譯的代碼,或者改變某些內容而不影響代碼的含義。您無法更改訪問說明符,並且會默默地導致調用不同的函數。

作爲一個人爲的例子,這裏是一個非常可怕的類接口:

public: 
    // Returns the amount of change tendered for this transaction. 
    MoneyAmount change() const; 

private: 
    // Account for a change of currency. Charges standard moneychanger's fee. 
    MoneyAmount change(Currency toCurrency = Currency::USD); 

如果無法訪問功能從重載決議刪除,客戶端代碼可以調用change()就好了。如果稍後第二個change(Currency)函數被公開並且第一個函數被刪除,那麼這個代碼會突然以一種完全不同的目的靜靜地調用另一個函數。當前規則防止更改訪問說明符以改變編譯程序的行爲。

0

在C++中,方法選擇(重載分辨率)在考慮公共/私有訪問控制之前發生。

0

改爲使用受保護的setter方法(或數據成員)而不是非const getter方法。

如果你有s.th,它沒有區別。像

class A { 
    SomeType foo_; 
protected: 
    SomeType& foo() { return foo_; } 

public: 
    const SomeType& foo() const { return foo_; } 
}; 

class A { 
protected: 
    SomeType foo_; 

public: 
    const SomeType& foo() const { return foo_; } 
}; 
6

成員訪問控制是調用一個成員函數時出現的最後一件事。它發生在名稱查找,模板參數推導,重載解析等等之後。之所以最後完成是因爲決定更改成員的訪問控制不應該突然改變客戶端代碼的執行。

想象一下,在重載解析之前檢查訪問,並且您在該庫中使用了庫和某個成員函數。然後,圖書館作者將這個功能變爲私人。突然間,您的代碼開始使用不同的過載,並以完全不同的方式運行。圖書館作者可能希望任何使用該函數重載的人都應該停止使用它,但他們不打算改變每個人的代碼。但是,由於標準實際上已定義,您的代碼現在開始向您提供使用私有成員的錯誤,而不是表現不同。

解決方法是簡單地更改您的受保護成員函數的名稱,以免它被考慮。

0

這就是C++的自然行爲,如果調用者代碼中的類的對象是非const的,那麼非轉換就被定義爲protected。您需要將類的對象定義爲const,或者在類的對象上使用const-cast,這將導致方法的const版本被調用。

#include <iostream> 
class Foo { 
    public: 
     const void bar() const { std::cout << " const version called\n";} 
    protected: 
     void bar() { std::cout << " non const version called\n";} 
}; 

int main(int argc, char** argv) 
{ 
    const Foo c; 
    c.bar(); // -> work 

    Foo c1; 
    c1.bar(); // compiler complain -> void Foo::bar() is protected 
    const_cast<const Foo&>(c1).bar(); // fine 
} 
相關問題