30章 内部クラス

http://www.geocities.jp/ky_webid/cpp/language/030.html

クラスの中でクラス宣言ができる。

これまたややこしい。。。

とりあえず実装してみます。

#include <iostream>
using namespace std;

class COuter {
public:
    class CInner {
    public:
        CInner() : m_num(100) {};
        int Get () const { return m_num; }
    private:
        int m_num;
    };
    int Get () const { return m_inner.Get(); }
private:
    CInner m_inner;
};

int main() {
    COuter obj;
    
    cout << obj.Get() << endl;
    
    return 0;
}
$ main
100

確かにうまくいってます。

クラスの中でクラス定義ができてますね。

CInnerを単独でインスタンス化することもできます。

その場合はどのクラスの内部クラスなのかを指定しないといけません。

int main() {
    // COuterクラスの内部クラスCInner
    COuter::CInner obj;
    
    cout << obj.Get() << endl;
    
    return 0;
}

上記のようにCOuter::CInnerとすることで、内部クラス単体でインスタンス化ができます。

ただし一般的には内部クラスを単体でインスタンス化するような実装はしないそうです。あくまでそのクラス内で使うだけのクラスなので単独で使用されたら好ましくないかもしれません。

そういう場合は内部クラスをprivate属性に宣言すれば単独の使用を禁じることができます。

#include <iostream>
using namespace std;

class COuter {
public:
    int Get () const { return m_inner.Get(); }
private:
    class CInner {
    public:
        CInner() : m_num(100) {};
        int Get () const { return m_num; }
    private:
        int m_num;
    };
    CInner m_inner;
};

int main() {
    // privateな内部クラスなのでインスタンス化できない
    COuter::CInner obj;
    
    cout << obj.Get() << endl;
    
    return 0;
}
$ cl /W4 /EHsc main.cpp
Microsoft(R) 32-bit C/C++ Optimizing Compiler Version 15.00.30729.01 for 80x86
Copyright (C) Microsoft Corporation.  All rights reserved.

main.cpp
main.cpp(20) : error C2248: 'COuter::CInner' : private class (クラス 'COuter' で宣言されている) にアクセスできません。
        main.cpp(8) : 'COuter::CInner' の宣言を確認してください。
        main.cpp(4) : 'COuter' の宣言を確認してください。