簡體   English   中英

const/non-const 重載解決問題

[英]Trouble with const/non-const overload resolution

我有一個看起來像這樣的 class:

class ClassA
{
  public:
    float Get(int num) const;
  protected:
    float& Get(int num);
}

在 class 之外,我調用 Get() function。

float foo = classAInstance.Get(i);

我希望這會調用公共版本,但 Visual Studio 會出錯:

error C2248: 'ClassA::Get' : cannot access protected member declared in class 'ClassA'

當注釋掉受保護的重載並刪除對它的所有引用時,代碼會編譯。

當一個可訪問的成員可用時,為什么編譯器會嘗試使用不可訪問的成員? 是否有一種公認的方式來強制編譯器選擇正確的重載? 是否在某處引用了成員函數的解析規則?

確實,重載決議發生在可訪問性檢查之前。 標准的第 13.3 節( [over.match] )說:

重載解析是一種機制,用於選擇最佳 function 來調用給定的表達式列表,這些表達式將成為調用的 arguments 和一組可以根據調用上下文調用的候選函數。 The selection criteria for the best function are the number of arguments, how well the arguments match the parameter-type-list of the candidate function, how well (for non-static member functions) the object matches the implicit object parameter, and certain other候選 function 的屬性。 [注:重載決議選擇的function不保證適合上下文。 其他限制,例如 function 的可訪問性,可以使其在調用上下文中的使用格式不正確。 ——尾注]

通常的解決方法是為公共和受保護的函數賦予不同的名稱。


請注意,這有時很有用,例如:

class Blah
{
    const std::string& name_ref;

    Blah(const char*) = delete;

public:
    Blah(const std::string& name) : name_ref(name) {}

    void do_something_with_name_ref() const;
};

std::string s = "Blam";
Blah b(s); // ok

請注意, name_ref只會從中讀取,因此將其設為const是合適的。 但是, const引用可以綁定到臨時對象,而將name_ref綁定到臨時對象將是一個懸空引用,從而導致do_something_with_name_ref()中的未定義行為。

Blah c("Kablooey!"); // would be undefined behavior
                     // the constructor overload makes this a compile error

私有構造函數重載防止臨時std::string被隱式構造和綁定。

重載解決首先完成,然后訪問檢查。

如果你同時有一個 const 和一個非常量重載,這可以通過 object 的 constness 解決,需要 function。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM