OS XP::VC++ 6.0
右から演算するのと左から演算するのと結果が異なる演算子を設定したいのですが、
(XA≠AX)
それぞれ、右オペランドの演算メソッドだけを定義するため、両方のクラスのヘッダー
ファイルを相互includeしたいのですができません。
このようなことはできないのでしょうか?
//////A.hの内容
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#include B.h
class CA
{
public:
CA();
virtual ~CA();
int data ;
CA operator / (CB b) { return b.data/(this->data * 3.0) } ;
};
//////B.hの内容
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#include A.h
class CB
{
public:
CB();
virtual ~CB();
int data ;
CB operator / (CA a) { return a.data/(this->data * 2.5) } ;
};
一部修正します。
// A.hの内容
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#include B.h
class CA
{
public:
CA();
virtual ~CA();
CA(int adata){this->data = adata;}
int data ;
CA operator / (CB b) { return CA(b.data/(this->data * 3.0)) } ;
};
// B.hの内容
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#include A.h
class CB
{
public:
CB();
virtual ~CB();
CB(int adata){this->data = adata;}
int data ;
CB operator / (CA a) { return CB(a.data/(this->data * 2.5)) } ;
};
相互に include する必然がある場合のお約束として
・ヘッダファイル中では相互 include はしない
・代わりに「クラス宣言」だけを書く
・関数宣言は .h に書く
・関数定義は .cpp に書く
とする(そうせざるを得ない)つまりインラインで定義は出来ない
operator / がメンバでなきゃならないかい?
二項演算子なので非メンバでも実装できるわけだが
---a.h---
class CB; // CB というクラスがあるよ (その詳細は今は知ることが出来ない)
class CA {
CA operator / (const CB& b); const // 宣言のみ
};
---b.h---
class CA; // CA というクラスがあるよ (その詳細は今は知ることが出来ない)
class CB {
CB operator / (const CA& a); const // 宣言のみ
};
---a.cpp---
#include a.h
#include b.h
// 両方を include した後でないと関数定義できないのでここで
CA CA::operator / (const CB& b) const { ... }
---b.cpp---
#include a.h
#include b.h
CB CB::operator / (const CA& b) const { ... }
> ・関数定義は ***.cpp に書く
> とする(そうせざるを得ない)つまりインラインで定義は出来ない
インライン定義できないということはないと思います。
### A.h ###
#pragma once
class CB;
class CA
{
public:
CA(void) {}
~CA(void) {}
CA operator / (const CB& b) const { return CA(); }
};
### B.h ###
#pragma once
class CA;
class CB
{
public:
CB(void) {}
~CB(void) {}
CB operator / (const CA& a) const { return CB(); }
};
### stdafx.h ###
#include A.h
#include B.h
> インライン定義できないということはないと思います。
CAでCBの実態を使ってないじゃん。
次の事例でもインライン定義できるんですか?
class CA {
...色々略
CA operator / (CB b) { return CA(b.data/(this->data * 3.0)); }
};
class CB {
...色々略
CB operator / (CA a) { return CB(a.data/(this->data * 2.5)); }
};
>> ・関数定義は ***.cpp に書く
>> とする(そうせざるを得ない)つまりインラインで定義は出来ない
> インライン定義できないということはないと思います。
インライン定義できないということはない=有用なインラインはほとんど不能
なので、「インラインで定義は出来ない」と言っても差支えないと思います。
まあフツーに「クラス定義内インライン関数」にするのは無理だけど
小細工を駆使してインライン化することは必ずしも不可能ではないので例題
除算をメンバーにしないのが前提
---a.h---
#if !defined(A_H_INCLUDED)
#define A_H_INCLUDED
class CB; // クラス宣言のみ
class CA { ... }; // クラス定義
CA operator / (const CA& a, const CB& b); // 宣言のみ
#endif // A_H_INCLUDED
---b.h--- ditto
---ab_impl.h---
#if defined(A_H_INCLUDED) && defined(B_H_INCLUDED)
inline CA operator / (const CA& a, const CB& b) { ... }
inline CB operator / (const CB& b, const CA& a) { ... }
#else /* A/B */
#error both a.h and b.h must be previously included
#endif /* A/B */
---main.cpp---
#include a.h
#include b.h
// 両者を include した後で
#include ab_impl.h
int main() { /* CA と CB で除算して味噌 */ }
まあ基本的にクロス依存関係を持たせないように設計するのがよさそうな希ガス
・二項演算子をクラスのメンバにしない
・互いがポインタや参照を持ちあったりしない
・演算子関数が public メンバしか使わない
のであればもっと簡単になって
---a.h---
class A { ... }; // 必ずしも B について知っておく必然は無い
---b.h---
class B { ... }; // ditto
---ab_impl.h---
inline A operator / (const A& a, const B& b) { ... }
inline B operator / (const B& b, const A& a) { ... }
====ENDOFSAMPLE====
ab_impl.h では #include され済みかどうかのチェックも不要
(忘れていたらコンパイルに通らないわけで 🙂
・二項演算子をどうしてもクラスのメンバーにしなきゃならない場合
・ポインタや参照を持ち合う必要がある場合
には先の例のごとく、知っておかねばならない相手クラスの(先行)宣言を行った後、
自分自身のクラス定義を行うというテクニックが必要となるわけだ
・演算子が private/protected メンバを使う必要がある場合
には演算子関数に対する friend がクラス定義中で必要、
そのためには演算子関数を関数宣言できるだけの名前が一式すべて必要、
ということはやはり相手クラスの(先行)宣言が必要、っつーわけだな
tetrapodさん、ひろさん、たいちうさん、επιστημηさんレスありがとうございます。
これまでは、子クラスのヘッダは、インクルードできないものだと思っていました。
そんなことがあれば、プログラミングスタイルがすごく制限されますね。
とっても役にたちました。
重ねてありがとうございました。