サブクラスから、派生元クラスの外部に公開したくないメンバを呼び出したい
事案
class C { protected: int member; // 公開したくないメンバー }; class D : public C { public: void func(const C& c) { cout << c.member << endl; // Cのmemberを使いたい } };
これはコンパイルエラーとなる。このように引数に渡した派生元クラスのメンバを呼び出したい。const D& dなら同じクラスのため可能である。
friendで解決
クラスフレンドを用いて、サブクラスに対して全てのメンバを公開する手法が考えられる。
class C { friend class D; protected: int member; }; class D : public C { public: void func(const C& c) { cout << c.member << endl; } };
publicにしちゃう
C自体はインスタンス化できないとして、publicなメンバーにすることで参照可能となる。派生先でusing C::member;をprivateにいれることでD自体ではアクセスできなくなる。ただし煩雑な上、書き忘れるとpublicになってしまう重大な欠陥がある。
class C { public: int member; // 公開したくないメンバー protected: C(int x) : member(x) { }; private: C(C& self) = delete; C(C&& self) = delete; }; class D : public C { public: D(int x) : C(x) { } void func(const C& c) { cout << c.member << endl; // Cのmemberを使いたい } private: using C::member; };
インナークラスにする
インナークラスは、外側のクラスのメンバーに内部でアクセス可能である。おそらくこれが最も良い方法だろう。
class C { public: class D; protected: int member; // 公開したくないメンバー C(int x) : member(x) { }; }; class C::D : public C { public: D(int x) : C(x) { } void func(const C& c) { cout << c.member << endl; // Cのmemberを使いたい } };
外部でDと使いたい場合は、
using D = C::D;
や
typedef C::D D;
とする。