2

カスタム データ構造を実装しているときに、興味深いジレンマに直面しました。残念ながら、C++11 標準で答えが見つからなかったので、誰かが私に説明してくれることを願っています。

ネストされたプライベート クラスを持つクラスがあります。また、このプライベート サブクラスをパブリック関数の戻り値として使用します。このような:

class Enclosing {
private:
    // Private nested class
    struct Nested {
        Nested(int x) : _x(x) {}
        int _x;
    };

    Nested _nested;

public:
    Enclosing():_nested(42) {}

    // Use private nested class in public interface
    const Nested& get_nested() {
        return _nested;
    }
};

結果を格納するget_nestedタイプのローカル変数を作成することはできませんが、呼び出しを使用しようとするとコンパイルされます。Enclosing::Nestedしかし、これはauto救助に来るところです:

int main() {
    Enclosing e;
    //Enclosing::Nested n = e.get_ref( ); //Error! Enclosing::Nested is private
    auto n = e.get_nested( );             //Ok, unless we name a type
    cout << n._x << endl;
}

さらに、いくつかの可変個引数テンプレート マジックを使用すると、ネストされたクラスのコンストラクターを呼び出して、その新しい見本を作成することもできます。

template<class T, typename... Args>
T* create(const T& t, Args... args) {
    return new T(args...);
}

int main() {
    Enclosing e;
    // We can even create a new instance of the private nested class
    auto np = create(e.get_nested( ), 68); 
    //Enclosing::Nested* np = create(e.get_nested( ), 68); // But don't name a type
    cout << np->_x << endl;
}

誰か私にこの振る舞いを説明してもらえますか? ではなぜautoプライベートなデータ型へのアクセスを許可するのですか? 今のところ目に見えない明らかな理由があるに違いありません。基準のパラグラフへの参照は大歓迎です。

どうもありがとうございました!

(gcc 4.7.3 および clang 3.2 でチェック済み)

4

1 に答える 1

1

それを説明する複製に加えて、内部クラスのメンバーをプライベートにし、外部クラスを として宣言することにより、プライベート クラスの作成者の意図を実際に改善friendできます。そうすれば、秒の例 ( create) はもうコンパイルされません (実際には、明示的でプライベートな copy-ctor も追加します):

class Nested {
    Nested(int x) : _x(x) {}
    int _x;
    friend class Enclosing;
};

これにより、 のすべてのインスタンスNestedが から作成されることが保証されEnclosingます。

于 2013-09-16T20:45:55.190 に答える