'CImageTemplate' : 指定の指定のテンプレート クラスはすでに定義されています
と言われてしまいます.
まだC++の知識が浅いのですが間違っている箇所がわかれば教えてください.
---------テンプレートのヘッダ(ImageTemplate.h)---------
template <class TempData> class CImageTemplate{
private:
TempData **Data;//データ本体
…
protected:
…
InitData(int h, int w);
};
---------テンプレートのcpp(ImageTemplate.cpp)---------
#include "stdafx.h"
#include "ImageTemplate.h"
template<class TempData>CImageTemplate<TempData>::InitData(int h, int w)
{…}
---------呼び出し側のヘッダ(ImageLabel.h)---------
#include "ImageTemplate.h"
class CImageLabel{
private:
CImageTemplate < int > Label;
…
};
---------呼び出し側のcpp(ImageLabel.cpp)---------
#include "stdafx.h"
#include "ImageLabel.h"
#include "ImageTemplate.h"
CImageLabel::InitLabel(int h, int w)
{
if(!Label.CheckData()){
Label.InitData(h, w);
}
}
No.4ベストアンサー
- 回答日時:
クラスが多重定義である旨のエラーが出るのは、ANo.2、ANo.3 の方のおっしゃるとおり、いわゆるインクルードガードが無いのが原因です。
まぁ、それはそれとして、それよりも大事な ANo.1 の方の回答を補足すると、要するにテンプレートクラスの定義は *.h の中に書くべきものであり、*.cpp に書いてはダメということです。
もちろん、*.h は最後にはどれかの *.cpp にインクルードされてコンパイルされるわけであり、インクルードするということは *.cpp の中に直接記述するのと同じですから、*.cpp の中に書いても当然コンパイルは可能なわけで、これは違反でもなんでもないわけですが、次の理由で意味が無いのです。
コンパイルの過程は A.cpp をコンパイルして A.obj をつくり、次にその A.obj をリンクして実行形式 A.exe をつくるという具合に進みますが、テンプレートクラスの定義だけを例えば A.cpp に書いてコンパイルしても、テンプレート引数の型が未定なので、中間ファイルである *.obj を作りようが無いのです。これは、何かの入れ物を作ってくださいと言われたけれど、何を入れるのか不明な状態では、どのぐらいの大きさのどんな形の入れ物を作れば良いのかわからないというのに似たような状況です。
なので、普通は、テンプレートクラスの定義は全て *.h の中に記述します。
*.h が *.cpp にインクルードされて、そこでテンプレート引数の型を与えられてクラスオブジェクトが具現化されて始めて *.obj が作成可能になるのです。
テンプレートクラスのメンバ関数も普通はクラスの内部に記述します。
例えば、
template <class T_param>
class CSomething {
public:
void MemberFunc() {} // クラスの中で定義する。
};
というような感じになります。
上記の MemberFunc() は次のようにクラスの外(ただし、ヘッダの中)に定義することも可能ですが、とても冗長な記述になるので普通はこのようにはしません。
template <class T_param>
class CSomething {
public:
void MemberFunc(); // プロトタイプ宣言をして、
};
template <class T_param>
void CSomething<T_param>::MemberFunc() {} // クラスの外で定義する。
健闘を祈ります。
大変お礼が遅くなって申し訳ありませんでした.
まだまだC++は勉強不足だということがわかりました.
みなさんの回答大変参考になりました.ありがとうございました.
No.3
- 回答日時:
No2の方と同じく#ifdefガードがヘッダーに無いためだと思います。
ヘッダーとソースに分割されたクラステンプレートを実際に使用するためにソースに向かってクラステンプレート側ソースをインクルードする必要があります。
この場合ImageTemplateクラスを使用するソースに向かってImageTemplate.cppをインクルードする事になります。
ImageTemplate.cppに変更が加わるとインクルードした先をコンパイルし直しますが、インクルードした個所が複数に及ぶと、影響個所を検出できないのでめちゃくちゃなコードを作成される可能性があります。
それを避けるため変更の度にリビルドをかけるしかありません(VC6以外は知りません)。
上記の理由により、クラステンプレートの分割は可読性が高いものの、あまりお勧めできません、
その他にもVC6はテンプレートをコンパイルする能力に関しては沢山の問題を抱えています。
No.2
- 回答日時:
ImageTemplate.hを2回インクリュードしているためのエラーだと思います
ImageLabel.cppにおいてImageLabel.hをインクリュードしています
このインクリュードされたImageLabel.hでImageTemplate.hがインクリュードされます
cpp側で もう一度 ImageTemplate.hをインクリュードしていますからクラス宣言が重複します
#ifdef/#defeine/#endifディレクティブによる番兵を使うか
#pragma onceディレクティブで複数回のインクリュードを抑制しましょう
No.1
- 回答日時:
template<class TempData>CImageTemplate<TempData>::InitData(int h, int w)
VC6でtemplateを分割コンパイルすることはできません。
ImageTemplate.h内でインライン定義してみてください。
(FAQだと思いますがC++のtemplateは現実的にそういうものです)
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- C言語・C++・C# C++プログラミングコードにポリモーフィズムを取り入れ方を教えてください。 2 2023/06/09 11:17
- C言語・C++・C# 並列プログラミングのπ計算について 1 2022/07/16 22:30
- C言語・C++・C# c言語の問題です 3 2023/01/10 16:15
- C言語・C++・C# バイナリファイルをコピーするのにかかる時間を測りたいのですが実行するとFatel error:gli 2 2022/11/03 01:10
- C言語・C++・C# const char** p;のとき、free(p)でC4090エラーとなるのはなぜですか 3 2023/03/31 16:28
- C言語・C++・C# c言語の問題の説明、各所ごとに 5 2023/07/26 11:03
- C言語・C++・C# C言語のエラーについて 2 2022/07/11 13:56
- C言語・C++・C# プログラミング c言語 4 2023/03/07 01:05
- C言語・C++・C# c言語 プログラムのエラー 1 2023/02/11 20:31
- C言語・C++・C# c言語の問題です 課題1 (二分探索木とセット) 大きさ size の配列 array を考える。す 2 2023/01/10 21:08
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
FriendとPublicの違い。。。
-
エディットコントロールのイベ...
-
C++でJavaのStaticイニシャライ...
-
protected override について
-
継承を重ねた場合のコストはど...
-
MessageBoxを継承したい
-
MFCのドラッグ&ドロップについて
-
フォーム間でのオブジェクト又...
-
C++ protectedにアクセス不可
-
OnPaintとOnDraw関数の違いにつ...
-
個々の関数について継承してい...
-
クラスのアドレスを引数として...
-
継承したクラスを、継承元のク...
-
変数の後の点々
-
C++で継承元のクラスの代入演算...
-
MFCアプリのコマンドラインでパ...
-
イベントにAddHandlerされてい...
-
OnInitDialog()の関数の組み込み方
-
派生クラスから基本クラスprote...
-
DataGridViewのセルに斜線を引...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
FriendとPublicの違い。。。
-
既定のコンストラクタがない?
-
(UWSC) 「#32770」の意味わかり...
-
クラスのアドレスを引数として...
-
ダイアログ表示時にチェックボ...
-
イベントにAddHandlerされてい...
-
【ASP.NET】 独自で作成したク...
-
MFCアプリのコマンドラインでパ...
-
DebugクラスとTraceクラスの違い
-
ボタンのオーナードローについて
-
OnInitDialog()の関数の組み込み方
-
IncludeではなくClassで宣言す...
-
関数の呼び出し元の検索
-
このコンパイルエラーの意味に...
-
C++ protectedにアクセス不可
-
C++で継承元のクラスの代入演算...
-
DataGridViewのセルに斜線を引...
-
C#で通常のbuttonコントロール...
-
エディットコントロールのイベ...
-
CMainFrameクラスの使い方
おすすめ情報