[表示 : 全て 最新50 1-99 101- 201- 301- 401- 501- 601- 701- 801- 2chのread.cgiへ]
Update time : 07/16 11:48 / Filesize : 200 KB / Number-of Response : 824
[このスレッドの書き込みを削除する]
[+板 最近立ったスレ&熱いスレ一覧 : +板 最近立ったスレ/記者別一覧] [類似スレッド一覧]


↑キャッシュ検索、類似スレ動作を修正しました、ご迷惑をお掛けしました

C++相談室 part61



1 名前:デフォルトの名無しさん mailto:sage [2008/03/09(日) 19:37:43 ]
C++に関する質問やら話題やらはこちらへどうぞ。
ただし質問の前にはFAQに一通り目を通してください。
IDE (VC++など)などの使い方の質問はその開発環境のスレに
お願いします。

231 名前:>>182 mailto:sage [2008/03/23(日) 22:07:14 ]
>>229
> 「見える」→メンバ変数の値が取得できる。(getter)
> 「アクセス」→メンバ変数の値が書きかえれる。(setter)

ほら、全然理解できてない。

簡単な例でいうと、

int a, b;

class X {
private: int a;
};

class Y: public X {
 int foo(){ return a; }
 int bar(){ return b; }
};

ってやると、foo() の中で X::a をアクセスしようとするからエラーになるよね。

もし、C++ の private が変数を「見えなくする」なら bar() の b と同じように、
foo() は ::a を返すはずだろ?

これが、「見えなくなること」と「アクセスできなくなること」の違いなわけ。

これによる、影響は自分で調べてみてね。

>>230
まあ、それはそれでそれこそもっとよく考えろとしか言えないわけだが...

232 名前:デフォルトの名無しさん mailto:sage [2008/03/23(日) 22:11:42 ]
何でこんな残念なスレになってしまったんだ。

233 名前:デフォルトの名無しさん [2008/03/23(日) 22:12:43 ]
だって にちゃん だもの

234 名前:デフォルトの名無しさん mailto:sage [2008/03/23(日) 22:56:01 ]
VSyncの話したらひどいことになりそう

235 名前:デフォルトの名無しさん mailto:sage [2008/03/23(日) 22:57:56 ]
>>231
初心者スレでやれ
ウザイ

236 名前:デフォルトの名無しさん mailto:sage [2008/03/23(日) 23:03:27 ]
結局>>182って文句言ってるだけで答えて無いじゃん

237 名前:>>182 mailto:sage [2008/03/23(日) 23:14:58 ]
答えは >>188 で既にでてるだろ。

まあ、10個ぐらいなら全部 friend 宣言してもいいと思うけど。

もしかして君も >>201 みたいに理解できてないやつなの? (w

238 名前:デフォルトの名無しさん mailto:sage [2008/03/23(日) 23:32:29 ]
>>188だとManager::getInstanceみたいなので取得するのと大差無いと思うが・・・

まぁ、それはともかく、>>180にfriendなどを使ってまで
制限する必要性があるのか、疑問だな。
クラスごと使わせなくするとこにfriendを使用している時点でおかしいと思う。

無名名前空間やdetails名前空間で十分なんじゃないか?


239 名前:201 [2008/03/23(日) 23:44:18 ]
>>231
>foo() の中で X::a をアクセスしようとするからエラーになるよね。

アクセッサをManagerの方に定義することを考えていたんだけどな。
「見える」「見えない」の話じゃんくてprivateだからだろ。

>もし、C++ の private が変数を「見えなくする」なら bar() の b と同じように、
foo() は ::a を返すはずだろ?

グローバル変数よりメンバ変数を参照しにいくのは知ってます。

Managerの方に「一部のクラス」に使わせたい機能だけ、protected または public にして
一部のクラスがManagerを継承すればいい。

Manager のprivateのメンバには「一部のクラス」も参照できない。

「一部のクラス」以外にManagerクラスのインスタンスを作られるのが困る場合は
コンストラクタなどをprotectedにすればいいんでは?


「一部のクラス」に対してManagerは一つらしいので、また違ってきますが・・・・



240 名前:デフォルトの名無しさん mailto:sage [2008/03/23(日) 23:58:52 ]
これで friend いらない

-- friends.cpp
#include "A.h"
#include "B.h"

namespace
{
class Manager {};
Manger& manager();
}


void A::f() { manager().a(); }

void B::g() { manager().b(); }


241 名前:>>182 mailto:sage [2008/03/24(月) 00:06:26 ]
>>238
> まぁ、それはともかく、>>180にfriendなどを使ってまで
> 制限する必要性があるのか、疑問だな。

それは、>>180 に聞いてもらわないとダメだけど、そう言う状況はありえると思うよ。

例えば、デバッグのためにマネージャの状態を直接見たりいじったりするクラスとか。
ただ 10個もあるのは、ちょっと多すぎるような気はするけどね。

>>239
頼むから、もう少し勉強してからレスしてくれ。
全然俺の言ってることが理解できてないよ。

242 名前:デフォルトの名無しさん mailto:sage [2008/03/24(月) 00:08:40 ]
で、アホなのはどっちなの?初心者なのでよく分かりません


243 名前:デフォルトの名無しさん mailto:sage [2008/03/24(月) 00:51:50 ]
>>242
やり方は色々ある。って話に落ち着けていいんじゃないのw
メイヤーズもそんなことeffective c++に書いてたでしょ。


244 名前:デフォルトの名無しさん mailto:sage [2008/03/24(月) 05:56:56 ]
>>242
「そいつの中にあるもの」の質はともかく、
「そいつの中にあるものを説明する能力」はどっこいどっこいです。

245 名前:デフォルトの名無しさん [2008/03/24(月) 17:47:39 ]
仮想関数を持たないクラスXとクラスYがあります。
YはXを継承しています。これらのクラスに対応する
インターフェイスのクラスIXとIYを以下のように定義しました。
しかし、コンパイルエラーでした。クラスYは抽象クラス
とみなされたようです。でも、クラスYはf()の定義も
g()の定義も持っているので抽象クラスではないように思えます。

XとYのインターフェイスを作る方法を教えて下さい。

class IX {
virtual void f() = 0;
};

class X : public IX {
void f() {}
};

class IY : public IX {
virtual void g() = 0;
};

class Y : public X, public IY {
void g() {}
};

int main()
{
Y y; // エラー(抽象クラスあるいは構造体のオブジェクトが宣言されています)
return 0;
}

246 名前:デフォルトの名無しさん mailto:sage [2008/03/24(月) 17:54:22 ]
 IX  IX
 ↑  ↑
  X  IY
  ↑↑
   Y

という継承木になっている。
X::IX::f は定義されているが、
IY::IX::f は定義されていない。

インタフェースクラスを作るなら、IX を仮想継承する必要がある。
ただ、それでも Y で f を定義する必要がある。

あと、インタフェースクラスに限らず、基底クラスには
必ず仮想デストラクタを定義するのを忘れないように。

247 名前:デフォルトの名無しさん [2008/03/24(月) 18:14:09 ]
>>246
ありがとうございます。
以下のように変更したらエラーが警告になりました。
この警告は無視していいような気がします。

>あと、インタフェースクラスに限らず、基底クラスには
>必ず仮想デストラクタを定義するのを忘れないように。
OKです。

class IX {
virtual void f() = 0;
};

class X : virtual public IX {
void f() {}
};

class IY : virtual public IX {
virtual void g() = 0;
};

class Y : public X, public IY {
void g() {}
};

int main()
{
Y y; // 警告('Y' : 2 つ以上のメンバが同じ名前を持っています。'X::f' から継承します。)
return 0;
}


248 名前:デフォルトの名無しさん mailto:sage [2008/03/24(月) 18:50:40 ]
Y::f では X::f と IY::f のどっちの実装を使えばいいのか分からないというもの。
まあ、今回の場合は IY::f に実装がないから X::f を使いますよという警告だけど、
Y に void f() { X::f(); } と書いておくのが無難。

249 名前:デフォルトの名無しさん mailto:sage [2008/03/24(月) 19:06:35 ]
class T
{
 T( int );
}

T *T_array = new T [100];
は出来ないじゃん?
#placement new使えってのはなしで。

std::vectorはどうやってこういうコンストラクタが引数を持ってるクラスを受け入れてるの?



250 名前:デフォルトの名無しさん mailto:sage [2008/03/24(月) 19:07:20 ]
placement newで

251 名前:デフォルトの名無しさん mailto:sage [2008/03/24(月) 19:11:33 ]
>>248
上の例では void f() 1個だけですが、実際のIXは純粋仮想関数を
22個もっています。Yに22個の関数をわざわざ定義するのはなんだか
無駄な気がするのですが。。。

252 名前:デフォルトの名無しさん mailto:sage [2008/03/24(月) 19:18:29 ]
>>251
まあ、面倒なら今のところは無視してもいいかもしれない。
コメントでも書いとこう。

253 名前:デフォルトの名無しさん mailto:sage [2008/03/24(月) 19:26:44 ]
>>241
頼むから、もう少しまともな説明してくれ。

254 名前:デフォルトの名無しさん mailto:sage [2008/03/24(月) 19:31:33 ]
>>252
わかりました。ありがとうございました。

255 名前:デフォルトの名無しさん mailto:sage [2008/03/24(月) 19:31:46 ]
friend 使うと「一部のクラス」が増えるとManagerも弄らないと駄目だな。

256 名前:デフォルトの名無しさん mailto:sage [2008/03/24(月) 19:34:11 ]
拡張性を敢えて犠牲にするなら、個別に friend するしかない。
拡張性もある程度考慮するなら基底クラス作ってそれだけ friend 。
あとは本人がどうしたいか、だな。

257 名前:デフォルトの名無しさん mailto:sage [2008/03/24(月) 20:12:41 ]
>>253
非常に初歩的な内容だし、あの説明で理解できないなら、
もうあきらめた方がいいぞ。

258 名前:デフォルトの名無しさん mailto:sage [2008/03/24(月) 22:58:50 ]
IDすら出ない板で煽り煽られ大変ですな


259 名前:180 mailto:sage [2008/03/24(月) 23:04:33 ]
私の為に喧嘩しないで><。



260 名前:デフォルトの名無しさん mailto:sage [2008/03/24(月) 23:59:31 ]
struct B{
 struct P{ B *temp; }
 B( P p ){ swap( *this, *(p.temp) ); }
 operator P (){ P p; p.temp = this; return p; }
};

B Return(){ return B(); }
void Accept( B &b ){};

------------
Accept( Return() ); //Error



俺、何間違えてるの?

261 名前:デフォルトの名無しさん mailto:sage [2008/03/25(火) 00:06:50 ]
設計?

262 名前:デフォルトの名無しさん [2008/03/25(火) 00:07:13 ]
エラーメッセージはキチンと書く

263 名前:デフォルトの名無しさん mailto:sage [2008/03/25(火) 00:09:50 ]


264 名前:デフォルトの名無しさん mailto:sage [2008/03/25(火) 00:11:00 ]
質問の仕方

265 名前:デフォルトの名無しさん mailto:sage [2008/03/25(火) 00:11:54 ]
>>263

266 名前:デフォルトの名無しさん mailto:sage [2008/03/25(火) 00:11:55 ]
Bにデフォルトコンストラクタないからとか?

267 名前:デフォルトの名無しさん mailto:sage [2008/03/25(火) 01:12:43 ]
Humanクラスを基底クラスとするTanakaやAsouやIshikawaクラスがあるとします
Humanは抽象クラスとして用いるつもりです
このときHumanにあるstaticメソッドを一回だけ呼び出したいときってどうすればいいでしょうか?
Humanのコンストラクタで呼び出したとすると、TanakaやAsouのコンストラクタでも呼び出されますよね
static bool initのような変数をフラグとして使う方法は思いついたのですが、
もっとスマートな方法はないのでしょうか?

268 名前:デフォルトの名無しさん mailto:sage [2008/03/25(火) 01:16:38 ]
シングルトンやそれに関わるC++の実装は非常に面倒くさくて
自分で一からやろうと思うとどうしても乱雑になる。
マルチスレッドが入ってくるともっと面倒くさくなる。

269 名前:デフォルトの名無しさん mailto:sage [2008/03/25(火) 01:25:21 ]
>>260
人生、かな?



270 名前:デフォルトの名無しさん mailto:sage [2008/03/25(火) 01:49:26 ]
>>267
そのメソッドを呼び出したいのは、Human派生のオブジェクトを生成したタイミングなの?

271 名前:267 mailto:sage [2008/03/25(火) 02:13:35 ]
>>270
そうですね
Human派生のオブジェクトを生成する前に呼び出しても構わないのですが

272 名前:デフォルトの名無しさん mailto:sage [2008/03/25(火) 02:30:23 ]
>>271
であれば、全てが始まる前に自分で一度だけ呼ぶのが良いと思うな。

273 名前:デフォルトの名無しさん mailto:sage [2008/03/25(火) 02:31:52 ]
>>272
それはstaticな変数をフラグにするよりダメじゃねぇかw

274 名前:267 mailto:sage [2008/03/25(火) 02:39:11 ]
>>272
あぁそうか、そもそもstaticなメソッドなわけだから

int main(){
   Human::onlyOnceCalled()

みたいなかんじで
最初の方で適当に呼んでおくってのもありかもしれませんね
一回だけしか呼ばないって保証がないような気もしますが

275 名前:デフォルトの名無しさん mailto:sage [2008/03/25(火) 02:49:38 ]
>>274
必ず最初に読んでしまってよいなら、クラスにスタティックなメンバを定義して
それの初期化の中で実行させてみては?

// human.h
class Human() {
 // 中略
 class Initializer { Initializer() { onlyOnceCalled(); } };
 static Initializer init;
};

// human.cpp
Human::Initializer Human::init;

文法間違ってたらすまん

276 名前:275 mailto:sage [2008/03/25(火) 02:51:47 ]
Human::Initializerのコンストラクタがpublicになってないとか、いろいろダメだorz
そこは適当におぎなって

277 名前:267 mailto:sage [2008/03/25(火) 03:01:51 ]
>>275
なるほど。こういう方法もあるんですね
勉強になりました
ありがとうございました

278 名前:デフォルトの名無しさん mailto:sage [2008/03/25(火) 03:05:20 ]
保証が欲しかったのか。失礼。
initialization orderを気にするならこんな感じかな。
class Human() {
class Initializer {
Initializer() { onlyOnceCalled(); }
public:
static void Initialize() { static Initializer instance; }
};
};

これで、Initializer::Initializeを呼んだタイミングで一度だけ初期化されるようになるよ。ただしこの場合は複数スレッドとかが動き出す前に呼んでね。

279 名前:260 mailto:sage [2008/03/25(火) 09:32:50 ]
ぇ?コンパイル通る?
gccだと通らないんだけど・・・



280 名前:デフォルトの名無しさん mailto:sage [2008/03/25(火) 09:53:30 ]
>>279
どこを見てそう思うんだよ・・・
指摘してくれてるだろ
>>263
>>266
あとAcceptがReturnの返す一時オブジェクトを参照してるから何とかしよう

281 名前:デフォルトの名無しさん mailto:sage [2008/03/25(火) 11:14:49 ]
>>279
まずは省略や手抜きをせずに、Bの定義を全部書け。
そして何をしたいのかはっきりさせろ。

282 名前:260 mailto:sage [2008/03/25(火) 16:02:29 ]
いや、やりたいことは下のやつを知りたかっただけ。
ja.wikibooks.org/wiki/More_C%2B%2B_Idioms/%E6%89%80%E6%9C%89%E6%A8%A9%E7%A7%BB%E5%8B%95%E3%82%B3%E3%83%B3%E3%82%B9%E3%83%88%E3%83%A9%E3%82%AF%E3%82%BF(Move_Constructor)
に書いてあることってnon-const referenceを受けるべきとろこに一時オブジェクトを渡せるって話だと思って、
渡してみたらコンパイラ通らないどーん。な状況。


283 名前:デフォルトの名無しさん mailto:sage [2008/03/25(火) 16:44:42 ]
>>282
これで通った
struct B{
struct P{ B *temp; };
B(){}
B(P p){ swap( *this, *(p.temp) ); }
operator P () { P p; p.temp = this; return p; }
};
B Return(){ return B(); }
void Accept( B b ){};
int main(){ Accept( Return() ); }

284 名前:デフォルトの名無しさん mailto:sage [2008/03/25(火) 17:14:20 ]
参照渡しから値渡しに変更した理由が分からん

285 名前:デフォルトの名無しさん mailto:sage [2008/03/25(火) 17:18:44 ]
抽象クラスのメソッドの定義で質問があります
抽象クラスにおいて、自分自身のクラスへのポインタの引数を取るメソッドは不可能なのでしょうか?
たとえばこういうコードです
class Human {
  void foo(Human *human) = 0;
};

コンパイルエラーになってしまいますが、なぜそうなるのか分かりません
抽象クラスだから、インスタンスを作れないので
void (Human human);
のようなメソッドはだめですよね、でもポインタならいけると思うのですが


286 名前:デフォルトの名無しさん mailto:sage [2008/03/25(火) 17:20:52 ]
B::operator P()の戻り値から構築されるBの一時オブジェクトは非const参照のAccept(B&)では受け取れないんじゃ?

287 名前:デフォルトの名無しさん mailto:sage [2008/03/25(火) 17:23:26 ]
その発送は無かったわ、thisポインタというものが(ry
virtual書いてみたらどうかな?

288 名前:デフォルトの名無しさん mailto:sage [2008/03/25(火) 17:27:02 ]
一時変数を値渡しする理由は?const参照にしない理由が分からない。

289 名前:285 mailto:sage [2008/03/25(火) 17:32:20 ]
>>287
すいません元のコードではvirtualをつけてました
thisポインタは分かるのですが、この抽象クラスを継承したクラスの間でやりとりしたいことがあるのです
不勉強なので間違ってるかもしれませんが、「関連」というのをやりたいのです。
>>285の例でやるなら、一般的にはHumanクラスにHuman *hoge;みたいなポインタをメンバに持たせて関連付けするそうですが
関数の引数でやれないかと思いまして



290 名前:デフォルトの名無しさん mailto:sage [2008/03/25(火) 17:35:09 ]
>>288
const参照でもいいかもしれないけど、それ以上所有権を動かせなくならない?

291 名前:デフォルトの名無しさん mailto:sage [2008/03/25(火) 17:45:20 ]
Acceptに入ってからも譲渡するなら、
void Accept(B& b) {}
B b = Return();
Accept(b);
の方が良くないかな、それ以前に何のためのPなんだ?

292 名前:デフォルトの名無しさん mailto:sage [2008/03/25(火) 17:47:47 ]
>>285
どういう一般的例なのかちょっと分からないけど、
処理と情報を分ける実装の方が個人的にはスッキリするかな

んで、そのプログラムvirtualつけてエラーが出る理由が分からないんだけど…

293 名前:デフォルトの名無しさん mailto:sage [2008/03/25(火) 17:49:24 ]
あぁ、失礼した、operator Pはconst守るようにしてるのね
ごめん、俺が悪かった

294 名前:292 mailto:sage [2008/03/25(火) 18:06:34 ]
>>292
すいませんすごく単純なクラスを作り直し、実験してみると、エラーはでませんでした。

「抽象クラスをインスタンス化することができません」というエラーメッセージだったので、
質問させていただいたのですが、おそらく他のところにエラー.の原因があると思うのでもう一度見直してみます

295 名前:294 mailto:sage [2008/03/25(火) 18:09:51 ]
>>294の名前欄は>>285の間違いです

296 名前:デフォルトの名無しさん mailto:sage [2008/03/25(火) 19:45:31 ]
auto_ptrはauto_ptr_refクラスを介して対処している。
もう知っているかもしれないけど、
C++0xでは非const参照でも一時オブジェクトを受けられるようになる(右辺値参照)。

297 名前:デフォルトの名無しさん mailto:sage [2008/03/25(火) 22:07:18 ]
move semantics と rvalue reference &&

298 名前:デフォルトの名無しさん mailto:sage [2008/03/25(火) 22:23:46 ]
右辺値参照は何度もこのスレでも話されてるけど理解できん。

299 名前:デフォルトの名無しさん mailto:sage [2008/03/25(火) 22:33:41 ]
エラー出る出る言うなら、同じエラーが出る小さいプログラムを示せよ。
BやらPやらの例も、そもそもswapがないでコンパイル止まるしな。




300 名前:デフォルトの名無しさん mailto:sage [2008/03/25(火) 22:34:02 ]
右辺値及び左辺値(この二つは組)、参照の理解を固めてから見直すとよろし

301 名前:デフォルトの名無しさん mailto:sage [2008/03/25(火) 22:45:08 ]
>>298
簡単に言うと「swapでおk」ってこと。


302 名前:260 mailto:sage [2008/03/25(火) 23:08:35 ]
おなにーでさーせん。swapとかごめん。あと別に必要なかったかも。
コンパイル通った。
>>283と一緒かな?

class D {
 public:
  struct Proxy { Proxy( D *d ):d_( d ){}; D *d_; };
  operator struct Proxy () { return Proxy( this ); };
  D( struct Proxy p ) {};
  void operator = ( struct Proxy p ){};
  D(){};
  D( D &rhs ){};
  void operator = ( D &rhs ){};
};

D Return() { return D(); }

int main( int, char** ){
D d = R();

return 0;
}

Accept( D &d );ってのは間違ってたかも。
ようは、
D( const D &rhs )だと、オーナーシップの移譲とかでrhsに変更加えられない。で、
D( D &rhs )だと、右辺値を渡せない。
だから、Proxyを返して、ごにょごにょする。って話なのか。

303 名前:デフォルトの名無しさん [2008/03/27(木) 00:31:14 ]
Cの関数ポインタにC++のClassの実体化した関数ていれられますか?
ビルドエラーが出るんですけど、そもそもそんなの出来ない?

304 名前:デフォルトの名無しさん mailto:sage [2008/03/27(木) 00:54:49 ]
>>303
できない。
関数ポインタとメンバ関数ポインタは別物。

305 名前:デフォルトの名無しさん mailto:sage [2008/03/27(木) 01:38:47 ]
>>303
Windowsのコールバック関数みたいに
こっちから引数を渡せれば、どうにでもできる。

306 名前:デフォルトの名無しさん mailto:sage [2008/03/27(木) 01:54:41 ]
>>303
sizeofを使ってポインタサイズを調べてみると、あれびっくりサイズがデカイって分るよ。
どうやっても入りません、キャストしたら情報ロストします。

307 名前:デフォルトの名無しさん mailto:sage [2008/03/27(木) 02:00:59 ]
>>306
いろいろ勘違いしてるような。

308 名前:デフォルトの名無しさん mailto:sage [2008/03/27(木) 02:24:05 ]
>>307
どこを?
具体的にどうぞ。


309 名前:デフォルトの名無しさん [2008/03/27(木) 02:29:53 ]
>>304-306 のうち確実に間違っているのは >>305 です、要注意。



310 名前:デフォルトの名無しさん mailto:sage [2008/03/27(木) 02:49:53 ]
面倒だからboost::functionを調べてみ >303

311 名前:デフォルトの名無しさん [2008/03/27(木) 02:56:20 ]
詳しく説明した方がいいかと
要するに、メンバ関数ポインタがさす関数はvirtualである事もあって
インスタンスに仕込まれた仮想テーブルを参照して、関数テーブルのうちどの位置にあるものかを取得する必要がある。
また、関数はvirtualでないケースもある、この場合仮想テーブルには関数のアドレス情報はないので、関数メンバポインタ内に情報がなければならない。
関数メンバポインタはこれら複合情報で構成された構造体となっている。


312 名前:デフォルトの名無しさん mailto:sage [2008/03/27(木) 03:03:53 ]
どこが詳しいのか


313 名前:デフォルトの名無しさん mailto:sage [2008/03/27(木) 06:03:12 ]
それなりに詳しいと思うけど、
であるがゆえに「要するに」から始まっているのは間違いだと思う。

314 名前:デフォルトの名無しさん mailto:sage [2008/03/27(木) 07:26:14 ]
>>303
関数ポインタには入れられないが、
実体とメンバ関数ポインタの対を構造体にしたものを引数に取る
ラッパ関数を通して呼ぶことはできる。
もちろん、C 側ではその構造体を直接扱うことはできないから、
void * を通すなり不完全型を利用してポインタで扱うなりする必要はあるけど。

315 名前:デフォルトの名無しさん mailto:sage [2008/03/27(木) 07:39:53 ]
>>309
>>305はCのライブラリのコールバック使うときとかの対処法の話じゃね?
大抵はvoid*のパラメータ持ってるし。

316 名前:デフォルトの名無しさん mailto:sage [2008/03/27(木) 07:46:12 ]
virtual関係無いよね。

317 名前:デフォルトの名無しさん mailto:sage [2008/03/27(木) 08:15:45 ]
そもそも、C++のclassの実体化した関数って何?実体化って何を言ってるんだ
インスタンス増えたら関数も増えるとか思ってるのだろうか、理解に苦しむ

www.microsoft.com/japan/msdn/vs_previous/visualc/techmat/feature/jangrayhood/

318 名前:303 [2008/03/27(木) 08:50:26 ]
やりたいのは複数newしたクラスからCの関数叩くんですけどその時の引数にコールバック用のCの関数ポインタがあるんです
そしてその時呼んだ実体に関数ポインタによって帰ってくるようにしたいんです


319 名前:デフォルトの名無しさん mailto:sage [2008/03/27(木) 09:03:26 ]
引数を加えて、static関数で良いんじゃ?



320 名前:デフォルトの名無しさん mailto:sage [2008/03/27(木) 09:20:50 ]
>>317
非staticメンバ関数/インスタンスメソッドの事だとみんな理解してるよ。

>>318
コールバック関数のパラメタを汎用ポインタとかで指定できるなら、そこにオブジェクトのアドレスを入れて、コールバック関数内でキャストしてメンバ関数を呼ぶ。
パラメタを指定できないなら、コールバック関数から見えるスコープの変数にオブジェクトのアドレスを入れておき、コールバック関数からメンバ関数を呼ぶ。

321 名前:デフォルトの名無しさん mailto:sage [2008/03/27(木) 10:10:15 ]
クラスの関数ポインタはthisが略されてるようなもんじゃね

322 名前:デフォルトの名無しさん mailto:sage [2008/03/27(木) 10:31:11 ]
>>317
往生際が悪い、素直に自分の知識不足でしたと認めろ

323 名前:デフォルトの名無しさん mailto:sage [2008/03/27(木) 11:13:55 ]
>>317
そのあたりは処理系依存だろ

324 名前:デフォルトの名無しさん mailto:sage [2008/03/27(木) 13:09:21 ]
static メンバ関数を C のコールバックに登録するのってよく見るし実際に
やったこともあるんだけど、ほんとは extern "C" と extern "C++" の違いで
型が遭わないはずなんだよね。

だからって対応策がわかんないし、使ったことのあるコンパイラでは全部通るから
そのまま使っちゃうんだけどさ。

325 名前:デフォルトの名無しさん mailto:sage [2008/03/27(木) 13:35:22 ]
>extern "C" と extern "C++"
"C" とかの修飾は、識別子を外部にどういう規則で公開するかという点についての指定であって、スタックフレームの作り方の指定ではない。
機種依存なので、そっちにいけと事になるが、cdeclとpascalが違えば "C" を付加しても動作しない。
C型のスタックフレームを持つ関数として登録可能な関数なら、C型のコールバックに登録する事ができるという事。
そうでないなら、コンパイルが通ったとしてもうまくいかない。

326 名前:デフォルトの名無しさん mailto:sage [2008/03/27(木) 13:52:21 ]
>>325
スタックフレームとか実装に立ち入った話はしてない。言語概念上の型が違うんだよ。

327 名前:デフォルトの名無しさん mailto:sage [2008/03/27(木) 13:53:59 ]
>>326
力いっぱいデタラメぶちかまさない

328 名前:デフォルトの名無しさん mailto:sage [2008/03/27(木) 13:58:42 ]
知識不足は許容できるが嘘吐きになってはイカンぜよ

329 名前:デフォルトの名無しさん mailto:sage [2008/03/27(木) 14:03:56 ]
>>327-328
気持ちはわかる。きっとみんなこれらは同じものとして使ってるだろうし、
動作も問題ないだろうさ。

でも規格ではエラーにならないとダメなんだよ。はっきり書いてあるから。

7.5 "Linkage specifications" p1 より
> ... Two function types with different language linkages are distinct types even
> if they are otherwise identical.

gcc でもバグ扱いだ。
gcc.gnu.org/bugzilla/show_bug.cgi?id=2316



330 名前:デフォルトの名無しさん mailto:sage [2008/03/27(木) 14:06:37 ]
>>329
自分を嘘と虚栄で塗り固めるような真似はやめた方がいい、どこに突っ込み入っているのかすら理解できていないだろ。

331 名前:デフォルトの名無しさん mailto:sage [2008/03/27(木) 14:10:44 ]
静的メンバ関数はextern "C++"ではない






[ 続きを読む ] / [ 携帯版 ]

前100 次100 最新50 [ このスレをブックマーク! 携帯に送る ] 2chのread.cgiへ
[+板 最近立ったスレ&熱いスレ一覧 : +板 最近立ったスレ/記者別一覧]( ´∀`)<200KB

read.cgi ver5.27 [feat.BBS2 +1.6] / e.0.2 (02/09/03) / eucaly.net products.
担当:undef