きままにブログ

プログラミングを主とした私のメモ帳です。寂しいのでコメントください笑

サブクラスから、派生元クラスの外部に公開したくないメンバを呼び出したい

事案

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;

とする。