テンプレートの継承 後日談 – プログラミング – Home

テンプレートの継承 後日談
 
通知
すべてクリア

[解決済] テンプレートの継承 後日談

固定ページ 1 / 2

てんてく
 てんてく
(@てんてく)
ゲスト
結合: 20年前
投稿: 92
Topic starter  

さらに base を継承した baseXYZ を作成し、

#include <boost/any.hpp>
std::map<int, boost::any> g_any;

void test()
{
baseXY xy;
baseXYZ xyz;

g_any[10] = xy;
g_any[12] = xyz;

for(std::map<int, boost::any >::iterator it = g_any.begin();
it != g_any.end(); it++)
{
SendData(&boost::any_cast< *** >(it->second)); //エラー
}
}

*** の部分をどう書いていいのかわかりません。どなたかご教授ください。
よろしくお願いします。


引用未解決
トピックタグ
てんてく
 てんてく
(@てんてく)
ゲスト
結合: 20年前
投稿: 92
Topic starter  

って、これじゃ仮想にならない
std::map<int, boost::any*> g_any;

baseXY* p = new baseXY;
g_any[10] = p; //要キャスト

とか.


返信引用
DD.
 DD.
(@DD.)
ゲスト
結合: 19年前
投稿: 10
 

>って、これじゃ仮想にならない
>std::map<int, boost::any*> g_any;
仮想?上の例なら std::map< int, boost::any > でいいような気が?

例)
boost::any a;
a = 10;
std::cout << boost::any_cast< int >( a );


返信引用
DD.
 DD.
(@DD.)
ゲスト
結合: 19年前
投稿: 10
 

>って、これじゃ仮想にならない
>std::map<int, boost::any*> g_any;

ひょっとして

class Base {};
class BaseXY : public Base {};
class BaseXYZ : public Base {};

std::map< int, Base* >

ってことですか?


返信引用
てんてく
 てんてく
(@てんてく)
ゲスト
結合: 20年前
投稿: 92
Topic starter  

ttp://rararahp.cool.ne.jp/cgi-bin/lng/vc/vclng.cgi?print+200512/05120021.txt

の通り、baseはtemplateで
std::map<int, base<> >
がどう書いていいか良くわからないんですよね。申し訳ないです。

前スレの件と前後するのでどう説明していいかも微妙なんですが

あるスレッド1は メッセージA でTYPE_XYのデータを受け取りたい。また
あるスレッド2は メッセージA でTYPE_XYZのデータを受け取りたい。さらに
スレッド3~が存在する場合もありそのときは メッセージA でTYPE_XYZθ を受け取りた
い。
各スレッドへのデータ送信は同時に行われる事が多い。

という条件で

void メッセージAを各スレッドに送る()
{
for(......)
{
send(送り先、メッセージA、データ);
}
}

こういう関数を実現したいんです。
このための手段としてtemplateと仮想関数の実装をしていたのですが
慣れないものでつまずきっぱなし(TT


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

> std::map<int, base<***> >

template<class T>
std::map<int, base<T>* >
とか?


返信引用
DD.
 DD.
(@DD.)
ゲスト
結合: 19年前
投稿: 10
 

ふと思いました。

用は baseXY or baseXYZ クラスでそれぞれ異なる構造体を扱いたいんですよね?
なら base クラスを template にする必要はない様な気がします。
むしろ構造体のほうを継承してやる。

こんなかんじでいいのかな?

struct TYPE
{
int type_;
};

struct TYPE_XY : public TYPE
{
int x_;
int y_;
};

struct TYPE_XYZ : public TYPE
{
int x_;
int y_;
int z_;
};

class base
{
public:
base( TYPE* type ) : type_( type ) {}
TYPE* Get() { return type_; }
private:
TYPE* type_;
};

int main()
{
TYPE_XY type_xy;
TYPE_XYZ type_xyz;

type_xy.x_ = type_xy.y_ = 1;
type_xyz.x_ = type_xyz.y_ = type_xyz.z_ = 2;

std::map< int, base* > type_map;

type_map[0] = new base( &type_xy );
type_map[1] = new base( &type_xyz );

std::cout << static_cast< TYPE_XY* >( type_map[0]->Get() )->x_;
std::cout << static_cast< TYPE_XYZ* >( type_map[1]->Get() )->z_;
}


返信引用
てんてく
 てんてく
(@てんてく)
ゲスト
結合: 20年前
投稿: 92
Topic starter  

>RAPTさん
回答ありがとうございます。でも
template<class T>
map<int, base<T> > data; って、コンパイル通んないっす。。

>DDさん
異なる構造体を扱いたいのは間違いないのですが、明示的なキャストを避けて使えるのもが
欲しいかなと(^^;
もうちょっと研究してみます。

もし何かいい方法ご存知でしたらアドバイスお願いします。


返信引用
REE
 REE
(@REE)
ゲスト
結合: 23年前
投稿: 240
 

>明示的なキャストを避けて使えるのもが欲しいかなと(^^;

継承と仮想関数は、同じ型として扱える場合に効果があります。

下記のようなものではだめでしょうか?

class Base {
void *p;
public:
virtual size_t GetSize() const =0;
void *GetDataPtr() const{return p;}
Base(void *pp):p(pp){}
};

class BaseXY : public Base {
TYPE_XY data;
public:
BaseXY():Base(&data){}
size_t GetSize() const{return sizeof(data);}
};


返信引用
REE
 REE
(@REE)
ゲスト
結合: 23年前
投稿: 240
 

補足
 GetDataPtrも仮想にすれば、メンバのpは不要になります。


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

> map<int, base<T> > data; って、コンパイル通んないっす。。
map<int, base<T>* >
と書いたのですが。(第二引数の型はポインタ型)

ちなみに、ポインタにしてもしなくてもコンパイルは通ったのですが、
一体ドコに上記のコードを書いたのでしょうか。


返信引用
てんてく
 てんてく
(@てんてく)
ゲスト
結合: 20年前
投稿: 92
Topic starter  

返信遅くなってしまってすみません。

>REEさん
class base {
public:
virtual size_t size() const =0;
virtual void* Get() = 0;
base(){}
~base(){}
};

class baseXY : public base {
TYPE_XY* data;
public:
baseXY(TYPE_XY* rhs){ data = rhs;}
~baseXY(){ delete data;} // new されることを想定
virtual size_t size()const {return sizeof(*data);}
virtual void* Get(){return data;}
};

こういうことでしょうか?

>RAPTさん
template <class T>
std::map<int, base<T>* > data;
グローバルです。

error C2262: 'data' : 壊せません。
error C2133: 'data' : サイズが不明です。

のように怒られてしまいます。


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

template と継承派生は generics を、逆というか横というか、とにかく、
違う方向から追求しているものなので、自分が今設計しているものにより適合するのが
どちらであるかをよく考えた上で選択する必要があります。

とりあえずこんなのを作ってみました。参考になれば幸い。

#include <iostream>
#include <vector>
#include <boost/shared_ptr.hpp>

struct base {
virtual ~base() {}
virtual void do_something()=0;
};

struct x : public base {
virtual void do_something() { std::cout << x << std::endl; }
};

struct y : public base {
virtual void do_something() { std::cout << y << std::endl; }
};

typedef std::vector<boost::shared_ptr<base> > myvec;

int main() {
myvec v;
boost::shared_ptr<base> xx(new x); v.push_back(xx);
boost::shared_ptr<base> yy(new y); v.push_back(yy);
for (myvec::iterator it=v.begin(); it!=v.end(); ++it) {
(*it)->do_something();
}
return 0;
}


返信引用
てんてく
 てんてく
(@てんてく)
ゲスト
結合: 20年前
投稿: 92
Topic starter  

>template と継承派生は generics を、逆というか横というか、とにかく、
>違う方向から追求しているものなので、自分が今設計しているものにより適合するのが
>どちらであるかをよく考えた上で選択する必要があります。

派生先に(templateだとして)
T Get() = 0; //今回はこの部分を設計に関わる事項だと思っています
T& GetRef() = 0; //同上
size_t size()const = 0;

などを実装させるような仕組みにしつつ、
その派生クラスa, b 同士は横のつながりがあって std::vectorやmapでひと括りに
出来るものを目指してみたのですが・・・。
いろいろ助言を聞いてやってみたのですが明示的な型変換で躓いてしまいます。

そんな我侭なものは作れないのでしょうか??
ダメならダメで仕方が無いとは思っていますが
引き続き助言お願いします m(_ _)m


返信引用
REE
 REE
(@REE)
ゲスト
結合: 23年前
投稿: 240
 

baseXY と baseXYZは、共にbaseとして扱えるため、ひと括りに処理できます。
しかし、TYPE_XYとTYPE_XYZには、全く関連がないため、ひと括りに処理できません。
ひと括りに扱うには共通点が必要で、その共通部分だけをまとめて処理できます。


返信引用
固定ページ 1 / 2

返信する

投稿者名

投稿者メールアドレス

タイトル *

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