148

次のコードがコンパイルされて実行されることに少し驚きました (vc2012 & gcc4.7.2)

class Foo {
    struct Bar { int i; };
public:
    Bar Baz() { return Bar(); }
};

int main() {
    Foo f;
    // Foo::Bar b = f.Baz();  // error
    auto b = f.Baz();         // ok
    std::cout << b.i;
}

このコードが正常にコンパイルされるのは正しいですか? そして、なぜそれは正しいのですか?auto(予想どおり)名前を使用できないのに、プライベート型で使用できるのはなぜですか?

4

5 に答える 5

118

のルールautoは、ほとんどの場合、テンプレート タイプの推定と同じです。投稿された例は、プライベート型のオブジェクトをテンプレート関数に渡すことができるのと同じ理由で機能します。

template <typename T>
void fun(T t) {}

int main() {
    Foo f;
    fun(f.Baz());         // ok
}

また、プライベート型のオブジェクトをテンプレート関数に渡すことができるのはなぜですか? タイプの名前だけにアクセスできないためです。型自体はまだ使用可能であるため、クライアント コードに戻すことができます。

于 2012-11-23T16:32:37.470 に答える
112

名前にはアクセス制御が適用されます。標準の次の例と比較してください。

class A {
  class B { };
public:
  typedef B BB;
};

void f() {
  A::BB x; // OK, typedef name A::BB is public
  A::B y; // access error, A::B is private
}
于 2012-11-23T16:36:57.903 に答える
10

他の(良い)回答に追加するために、問題が実際にはまったく関係ないことを示すC++ 98の例を次に示しautoます

class Foo {
  struct Bar { int i; };
public:
  Bar Baz() { return Bar(); }
  void Qaz(Bar) {}
};

int main() {
  Foo f;
  f.Qaz(f.Baz()); // Ok
  // Foo::Bar x = f.Baz();
  // f.Qaz(x);
  // Error: error: ‘struct Foo::Bar’ is private
}

プライベート タイプの使用は禁止されていません。タイプに名前を付けるだけでした。たとえば、C++ のすべてのバージョンで、その型の名前のない一時ファイルを作成しても問題ありません。

于 2016-02-18T02:56:59.310 に答える
0

ここに来て回避策が必要な人のために(たとえば、プライベート型を受け入れる関数を宣言するため)、これが私がしたことです:

void Func(decltype(Foo().Baz()) param) {...}
于 2022-01-19T22:21:58.057 に答える