簡體   English   中英

使用自動訪問類的私有結構

[英]Accessing private struct of a class using auto

我發現下一個奇怪的代碼編譯並運行(在 VS 2019 上):

#include <iostream>

class Test
{
    private:
    struct Priv
    {
        int a;
    };
    
    public:
    static Priv WeirdFunc() {return {42};}; 
};

int main()
{
    auto val = Test::WeirdFunc();
    std::cout << val.a;
}

輸出是 42,這里沒有問題。

我看到的問題是 auto 關鍵字允許我們訪問私有結構“Priv”。 如果我嘗試用 Test::Priv 替換 auto ,我會得到編譯錯誤,正如預期的那樣。 從互聯網上的文章中,我發現您可以對 lambda 使用 auto,但從未提到過這種情況。

另外,如果我嘗試輸出“Test::WeirdFunc().a”,它也可以工作

所以我的問題是:

  • auto 允許我們訪問私有結構/類是預期行為嗎?
  • 是否允許聲明返回私有結構的公共函數?
  • 如果它是函數的返回值(例如“Test::WeirdFunc().a”),我們可以訪問私有結構/類是預期的行為嗎?

所有這些顯然都是糟糕的代碼風格,但我很好奇它是否是有效的 c++ 代碼

Test::WeirdFunc()的結果是一個Priv 這也是val的自動扣除類型。 auto關鍵字消除了將val的類型命名Priv的必要性,因此編譯器不會抱怨。 因此, val是(未提及的)類型Priv並且有一個公共成員a ,可以自由訪問。

因此,您所有問題的答案都是: Yes ,(只要您不“提及”嵌套類的名稱)。

另請參閱:嵌套類上的 cpp 參考

所以我的問題是:

  • auto 允許我們訪問私有結構/類是預期行為嗎?

是的。

  • 是否允許聲明返回私有結構的公共函數?

是的。

  • 如果它是函數的返回值(例如Test::WeirdFunc().a ),我們可以訪問私有結構/類是預期的行為嗎?

是的。

所有這些顯然都是糟糕的代碼風格,......

不,不一定。 考慮例如一個容器類,它將迭代器類定義為內部嵌套類型:

class Container {
     class iterator {
     public:
          iterator operator++(); 
          iterator operator++(int); 
     };

public:
     iterator begin();
     iterator end();
};

這允許通過auto訪問iterator的實例和操作,但不能直接從類外部創建實例。

您有一個公共接口,它通過公共接口的返回值類型公開類型 這實質上意味着您的 API 設計公開了類的私有細節,這不是 C++ 語言功能的問題,而是 API 設計的問題。 請注意,這不僅適用於auto

using A = decltype(Test::WeirdFunc());  // A is Test::Priv.
A a{};  // well-formed.

這是有效的,原因如下:

訪問說明符控制對名稱的訪問。

因此,您無權訪問名稱Priv ,但這並不意味着您無權訪問它所指的類型。 還有其他方法可以“實現”,例如使用auto

這並不像你想象的那么瘋狂。 畢竟,你不能用它做任何損害:如果你不希望公共事物返回“私有類型”的實例(這不是,真的,但沒關系),那么就不要做那件事。

暫無
暫無

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

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