テンプレートクラスの派生クラスをエクスポート – プログラミング – Home

テンプレートクラスの派生クラスをエクス...
 
通知
すべてクリア

[解決済] テンプレートクラスの派生クラスをエクスポート


いしだ
 いしだ
(@いしだ)
ゲスト
結合: 17年前
投稿: 53
Topic starter  

Visual Studio 2008や2010のMFCです。
以下のようなテストクラスを作成すると、ビルドは通ります。

class CTest
{
};

class CTestList : public CList<CTest>
{
};

void Test()
{
CTestList test;
test.AddHead(CTest());
test.AddTail(CTest());
test.GetCount();
}

これを、以下のようにMFC拡張DLLからエクスポートしようとすると、
operator==()が見つからないなどのコンパイルエラーが出てしまいます。

class __declspec(dllexport) CTest
{
};

class __declspec(dllexport) CTestList : public CList<CTest>
{
};

dllexportを付けない場合も、上記のTest()の中で

test.Find(CTest());

などと追加すると、同じようにコンパイルエラーになりますが、
使っていないうちはビルドできていました。
CList::Find()がoperator==()を使っているせいだと思われます。

これは、エクスポートせずに使っているうちは、
コンパイル中に必要になったメンバ関数だけが用意されるが、
エクスポートするクラスは無条件にすべてのメンバ関数を用意するため、
CListから呼ばれる可能性のあるすべての機能を用意しないとエクスポートできない
という解釈でよいのでしょうか。

このようなクラスは、どのようにエクスポートすればよいのでしょうか。
派生クラスにするのではなく、CList<CTest>をメンバとして持たせ、
使用したいCListメンバ関数を呼ぶ関数をCTestList自身にも載せる
とかになるのでしょうか。


引用未解決
トピックタグ
仲澤@失業者
(@uncle_kei)
Prominent Member
結合: 5年前
投稿: 828
 

簡単に言うと
1.クラスをエクスポートすると、それが提供する全ての
 「関数」及び派生元がエクスポートされなければならない。
です。何が使用されるかわからないので、全て実体が必要なわけです。

さて、発生したエラーを見ると、要素の比較オペレータが無い。
と言っているわけで、これはそもそもCList<T>を使用する上で不可欠な関数が
抜けているせいですね。それは、CTestのメンバー関数として必要で
public:
bool operator ==( const CTest & ex)
const
{
// 結果を戻してください
}
です。これを実装するだけで済みますよね。

さて、こういったことをせずに済ませたい方法としては、
メンバー関数ごとにエクスポートするという方法も考えられます。


返信引用
tetrapod
 tetrapod
(@tetrapod)
ゲスト
結合: 21年前
投稿: 830
 

俺としては、提示 CTestList を直接公開するのではなくて
> 派生クラスにするのではなく、CList<CTest>をメンバとして持たせ、
> 使用したいCListメンバ関数を呼ぶ関数をCTestList自身にも載せる
に1票。

こうしておけば CTestList の内部実装を変更することが簡単になる。
CList<CTest> をメンバに持たないようなクラスに変更することもできるわけだ。

派生クラスを直接公開する=実装変更に対する自由度が少なくなるので推奨しない。
# 技術的に可能であっても、やらないほうがいい例の1つ

そもそも今時 CList なんて過去の遺物を使うのは限りなくありえない。
使うなら標準コンテナだろう。


返信引用
いしだ
 いしだ
(@いしだ)
ゲスト
結合: 17年前
投稿: 53
Topic starter  

ご意見ありがとうございます。

設計としては、集合自体を表すものだったので、
has-a関係よりはis-a関係だと思い、このような継承をしてみたのですが、
DLLでエクスポートするのには向かないということになるのですね。

同じような名前の関数をバケツリレー的に呼ぶことになってしまいますが、
エクスポートクラスのメンバにする方法でやってみようかと思います。


返信引用
tetrapod
 tetrapod
(@tetrapod)
ゲスト
結合: 21年前
投稿: 830
 

うーん。
集合を表現するのには list でなくても vector でもデーターベースでもいいわけだ。
list/vector/map が別に用意されているのは性能面で置き換えができないからで、
技術論としては
・今想定している要望に対しては list が高性能であろう
・別の要望に対しては vector のほうが高性能であろう
ってなときに差し替えが利く設計のほうが有利なはず・・・とか俺は思う。
そのために1層バケツリレーがあってもいいんぢゃないかな。

・同じインターフェイスを設計しておけば
・違う実装にできる
っていうプログラム的要求を

・DLL ってのは「バイナリレベルで」実現する
・template ってのは「コンパイル時ソースレベルで」実現する
わけで、目的が違うものを混載するのは結局どっちつかずになるのが落ち。

DLL エクスポートすることが主目的なのであれば「バイナリレベル」互換が
維持しやすいようにするべきだと思う。
DLL 形式なら他コンパイラや他言語からも使えるわけだし。


返信引用

返信する

投稿者名

投稿者メールアドレス

タイトル *

プレビュー 0リビジョン 保存しました
共有:
タイトルとURLをコピーしました