These search terms have been highlighted:[c++]
2010-04-20
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 のメンバ変数を書き換えられる.