friend 属性を継承する
C++ では,クラスを継承しても friend 属性は継承されない.継承させたい場合,どうするか?
friend は使わない方がいいといわれることがあるが,operator<<や operator>> の定義など,使った方がよい場合もある (e.g. When should you use ‘friend’ in C++?).
問題設定
- クラス TItem は private メンバ変数 x_ を持つ.x_ はユーザに書き換えられてはならない
- なお,ユーザは TItem のインスタンスを作成できる
- クラス TTest は TItem を要素に持ち, x_ を書き換えることがある
- TItem はあくまで TTest の要素.TItem を派生させたりはしない
- ユーザがクラス TTest と類似のクラスを作られるようにしたい
- そのクラスは TItem の x_ を書き換えることがある
解
ユーザが作るクラスの識別子は不明なので,ユーザが作るクラスを TItem の friend クラスにするのは無理.
そこで,TItem の friend クラスを基本クラスとして作成,そこから TTest などを派生するようにする.ただし,派生しても friend 属性は継承されないから,基本クラスに TItem の private メンバにアクセスする関数群を作る.
例
#include <iostream> using namespace std; class TItem { private: double x_; friend class TBase; }; class TBase { protected: static double& x_(TItem &i) {return i.x_;} static const double& x_(const TItem &i) {return i.x_;} }; class TTest : public TBase { public: TTest(const double &init) { x_(i_)= init; // NOTE: i_.x_ は private なのでアクセスできない(TTest は TItem の friend じゃない) cerr<<"x_(i_) has been initialized by "<<x_(i_)<<endl; } private: TItem i_; }; int main(int argc, char**argv) { TTest t1(0.5); TTest t2(3.14); return 0; }
これで,ユーザは基本クラス TBase から派生させたクラスからでないと,TItem のメンバ変数を書き換えることは不可能.逆に,TBase から派生させたどんなクラスでも,TItem のメンバ変数を書き換えられる.