[英]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”,它也可以工作
所以我的問題是:
所有這些顯然都是糟糕的代碼風格,但我很好奇它是否是有效的 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.