はじめまして。けっずと申します。
初投稿です。これからよろしくお願い致します。
テンプレートの使い方が良くわかっておらず苦戦しております。
どなたかご存知の方いらっしゃいましたら、ご教授下さい。
宜しくお願いします。
開発環境:VC++.net 2003
質問内容
引数付きのコンストラクタをもつテンプレートクラスを継承する際に
どのように記述するのが正しいのか教えて下さい。
現在の症状としては、引数付きコンストラクタが呼び出せていません。
(error C2614 のコンパイルエラーが出ています)
ソースは以下のような状態です。(細かい所は割愛しています)
---------------------------------------------------------------
class CFirstMode
{
public:
CFirstMode( HWND );
};
template < class T, typename D >
class CTestModeRoot : public T
{
public:
CTestModeRoot( D );
virtual HRESULT ProcA( void )= 0;
};
template < class T, typename D > CTestModeRoot< T, D >::CTestModeRoot( D ) : T( D )
{
}
class CTestModeA : public CTestModeRoot< CFirstMode, HWND >
{
public:
CTestModeA( HWND = NULL );
virtual HRESULT ProcA( void );
};
CTestModeA::CTestModeA( HWND hParent ) : CTestModeRoot( hParent )
{
}
---------------------------------------------------------------
(意図としては動作環境に応じて継承するクラスを変えたいという趣旨のものです ※起動時に決定)
CTestModeAのコンストラクタでCTestModeRootが無いとコンパイルで怒られてしまいます。
(error C2614 のコンパイルエラーが出ています)
テンプレートを明示してやれてないのが問題だと思うのですが・・・
CTestModeA::CTestModeA( HWND hParent ) : CTestModeRoot< CFirstMode, HWND >::CTestModeRoot( hParent )
CTestModeA::CTestModeA( HWND hParent ) : CTestModeRoot< CFirstMode, HWND >( hParent )
CTestModeA::CTestModeA( HWND hParent ) : template < CFirstMode, HWND > CTestModeRoot( hParent )
template < CFirstMode, HWND > CTestModeA::CTestModeA( HWND hParent ) : CTestModeRoot( hParent )
上記のように書いたりして試しましたがいずれもダメでした。
どのように記述すれば引数付きコンストラクタを呼び出す事が出来るのでしょうか?
お手数をおかけしますが、ご教授お願いします。
正しい構文は以下。
CTestModeA::CTestModeA( HWND hParent )
: CTestModeRoot<CFirstMode, HWND>( hParent )
よって、二番目が正解。
提示コードでは、これをやってもエラーになりますが、
それは別のバグのせい。
template < class T, typename D >
CTestModeRoot< T, D >::CTestModeRoot( D ) : T( D )
↓
template < class T, typename D >
CTestModeRoot< T, D >::CTestModeRoot( D d) : T( d )
templateが実体化されてなかったのでエラーになってなかったが、
実際に呼ばれるようになったら、エラーが表面化している。
Banさん、ありがとうございます。
無事解決しました。本当にありがとうございます。
>(意図としては動作環境に応じて継承するクラスを変えたいという趣旨のものです ※起動時に決定)
# 予断ですが、templateには向かないと思いますが(コンパイル時にしか切り替えられないので)
Banさん、ご指摘ありがとうございます。
説明に問題がありました。誤解を招いてしまい申し訳ありません。
起動時に決定がそもそも間違いで、コンパイル時に決定でした。
コンパイルターゲットにより切り替えるといった趣旨のもので、
プリプロセッサの状態により分けているといったものです。
誤解を招かない質問を心がけたつもりですが、やっぱり抜けがあったようで
お恥ずかしい限りです。以後きをつけていきたいと思います。
>template < class T, typename D >
>CTestModeRoot< T, D >::CTestModeRoot( D d) : T( d )
微妙に、というか、二重三重に違和感が。
・ここで発生する引数オブジェクト d のコピーははたして可能か?
・常に引数は1個だけなのか?
あたりに俺は拒否反応を感じまくっているわけで。
> template < class T, typename D >
> class CTestModeRoot : public T
そもそも基底クラスがわからないのに適当に派生しちゃうわけ?
それってオブジェクト指向原理主義な人たちから総スカンを喰らいそうな気がする。
俺的にもこんなコードを書く選択肢はありえないと思う。
template<typename T> class CTestMode {
T obj;
};
でダメな理由があるなら俺の後学のために知りたいなーと思う。
> プリプロセッサの状態により分けているといったものです。
それでいいなら template みたいに難しい事考えずに
#if AAA
class XXXX : public YYY { ... };
#endif
#if BBB
class XXXX : publiz ZZZ { ... };
#endif
とするほうが後の手間がかからないような気がする・・・・
tetrapodさん、ご指摘ありがとうございます。
> それでいいなら template みたいに難しい事考えずに
> #if AAA
> class XXXX : public YYY { ... };
> #endif
> #if BBB
> class XXXX : publiz ZZZ { ... };
> #endif
> とするほうが後の手間がかからないような気がする・・・・
確かに仰るとおりで、ちょっと前までこちらでコーディングしてたのを
テンプレートにしてみました。
(その他にもいろんな所をテンプレート化して勉強中です)
特にこのコーディングにしなければという訳ではなくて
現在、テンプレートの勉強をしていて「こんなん組めるかな?」
といった好奇心から行ったものです。
それでテンプレートの引数付きのコンストラクタの呼び出し方が
私の持っているどの本にも載ってなかったので質問させて頂きました。
まぁ結局は
どの本にも載ってなかった=著者も想定してないイレギュラーケース
という事で、ご指摘の通り、実用LVでは無いのかもしれません。
ということでひとしきりテンプレートの勉強が終わったら
元のソースに戻そうかと思っています。
ツイート | ![]() |