C++相談室 part61
..
175:デフォルトの名無しさん
08/03/22 22:03:15
>>174
面白くないよ。mplの単なるリファレンス。
176:デフォルトの名無しさん
08/03/23 00:53:31
DLLを読み込み、一部の機能のみを使った場合、
メモリの消費量はまるまるDLL分増えるのでしょうか
それとも使った機能の分だけ増えるのでしょうか
177:デフォルトの名無しさん
08/03/23 01:03:35
環境依存の話はスレチだけど、まるまる増えると思うよ。
178:デフォルトの名無しさん
08/03/23 01:12:30
仮想メモリはまるまる
物理メモリはコードについては使った分
データはシラネ
179:デフォルトの名無しさん
08/03/23 01:30:13
ありがとうございました
使いたいライブラリが8MBくらいあるもので、
まるまる増えるのはちょっとアレかな、と思って質問しました
改変可なので、必要な部分だけ取り出そうと思います
180:デフォルトの名無しさん
08/03/23 03:06:24
Managerクラスがあり
その機能は、一部のクラス(と言っても10個ぐらいある><)
にしか利用できないって設計の場合
一部のクラスをfriendする以外に何か方法はありませんか?
181:デフォルトの名無しさん
08/03/23 03:13:01
その一部のクラス以外はmanagerクラスのインスタンスを手に入れられないようにする。
182:デフォルトの名無しさん
08/03/23 09:41:11
>>180
freind じゃダメな理由を書いた方が答えが得られやすいと思う。
183:>>182
08/03/23 09:42:51
ミスった... orz
freind ⇒ friend
184:デフォルトの名無しさん
08/03/23 09:45:07
friend先に依存が出来るからじゃね?
普通、friendは最終手段だし
185:デフォルトの名無しさん
08/03/23 12:07:26
そんなことはない。
186:>>182
08/03/23 13:05:05
friend 先に依存って何?
187:デフォルトの名無しさん
08/03/23 13:58:48
一部のクラスだけ特別扱いするというのがManagerクラスの仕様なら、
friendによる依存は妥当だと思う。
188:デフォルトの名無しさん
08/03/23 14:45:51
一部のクラスの基底クラスとして
Manager を取得するクラスを作って、
その1つだけを friend にすれば?
189:180
08/03/23 14:58:22
friendが結構な数になってしまうんです。
下手すれば私のリアルfriendより多いぐらい
それが悔しくて
190:デフォルトの名無しさん
08/03/23 14:59:16
誰が上手い事を言えと
191:184
08/03/23 15:01:24
俺は181に一票で
192:デフォルトの名無しさん
08/03/23 15:02:43
その方法を聞いてるんだろw
193:デフォルトの名無しさん
08/03/23 15:09:28
パスワード掛ければいいんじゃないですかね
194:デフォルトの名無しさん
08/03/23 15:14:48
w
195:デフォルトの名無しさん
08/03/23 15:25:03
権限プログラミングってのも面白そうじゃないか
196:デフォルトの名無しさん
08/03/23 15:42:23
singletonなら簡単なのにな
197:デフォルトの名無しさん
08/03/23 16:01:39
思い出したw
____
|← reject| boostの中の人 singleton ユーザー
. ̄.|| ̄ ̄ ┗(^o^ )┳(`Д´)┳(^o^ )┛≡=-
|| ┏┗ ┗┗ ┏┗ ≡=-
 ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄
198:デフォルトの名無しさん
08/03/23 16:06:07
ユーザーは欲してると思うが
199:デフォルトの名無しさん
08/03/23 16:34:52
にわかに得た知識で面白いこと考えた!
Managerのインスタンスを受け取る関数の引数に関数オブジェクトを使って
内部で一定のアルゴリズムで正しい値を返すもの(パスワードの暗号化みたいな)にのみそのインスタンスを渡してやる風にすればいいんじゃね?
更にインスタンスを受け取る関数をテンプレート化してやり、欲しい権限までのクラス型インスタンスを返すようにしてやればアクセス制限も出来て完璧!
とここまで考えてわざわざこんなことしてもオーバーヘッドが大きいだけなことに気づいた
そもそも何の意味があるんだっけか
200:デフォルトの名無しさん
08/03/23 16:45:12
だから >>188 でいいだろ、別に。
201:デフォルトの名無しさん
08/03/23 16:57:35
Managerクラスコンストラクタなどをprotectedにして、使うクラスはManagerを継承する。
202:デフォルトの名無しさん
08/03/23 17:02:41
>>188 >>199 >>201
これらの方法は、Managerクラスの許可なく好き勝手に権限のあるクラスを作れる。
そういうのを>>180は制限したいんじゃないの?
203:>>182
08/03/23 17:08:28
>>201
そう言うのは最悪。
あとから見て、継承が本当に必要だったのか、単に特定のメソッドを
使わせるために継承しているのかがわからなくなるから。
204:201
08/03/23 17:21:39
>>203
意味がよく分からないけど、、、「特定にメソッドを使わせるために継承が必要かどうかがわからなくなる」ってこと?
そんなこと言ってたら何もできない。
friendだったら、なぜfriendにしたか分からなくならないの?
friend よりいいと思うけどな。
friend じゃprivateのメンバにアクセスできてしまう。
Managerクラスを機能を利用するんだから、継承しかないでしょ。
使う側のクラスに持たせるとなると、コンストラクタとかはpublicになってしまうし。
205:デフォルトの名無しさん
08/03/23 17:40:32
継承すると
Managerの中のstaticでない変数とか勝手に作られない?
206:デフォルトの名無しさん
08/03/23 17:41:03
>>203
Manager クラスじゃなくて単に許可コントロール用の class を作る
というのは有りじゃない?そういう例をまともな本で見た記憶がある。
207:デフォルトの名無しさん
08/03/23 17:42:27
-カーズは-
2度と地球へは戻れなかった…。
鉱物と生物の中間の生命体となり
永遠に宇宙空間をさまようのだ。
そして死にたいと思っても死ねないので
―そのうちカーズは考えるのをやめた。
全部globalにすればいいじゃん
208:デフォルトの名無しさん
08/03/23 17:44:01
>>206
電波の缶詰の人のサンプルもそうだった
ライブラリ的なものを
外部からいじられないようにするためだったら
そんな感じでもいいんじゃまいか
村八分
209:デフォルトの名無しさん
08/03/23 17:47:19
Managerインスタンスを受け取るために、Managerにコールバックしてもらえばいいんじゃない?
class FriendClassA; // 前方宣言
class FriendClassB;
class Manager
{
public:
class Friend { public: virtual void authorize(Manager* m) = 0; };
void getInstance(Friend* p)
{
if( dynamic_cast<FriendClassA*>(p) ||
dynamic_cast<FriendClassB*>(p) ||
/* 権限のあるクラスかをチェック */ )
{
p->authorize(this);
}
}
};
210:デフォルトの名無しさん
08/03/23 18:25:34
それは、インスタンス取るのに時間かかるし
friendでいいじゃんって話になるも
211:デフォルトの名無しさん
08/03/23 18:40:51
速度が重要ならtemplate部分特殊化とかで。
class Manager
{
public:
template <class Unauthorized>
static void authorizedProc(unauthorizedClass * p)
{ std::cout << "not authorized" << std::endl; }
template <>
static void authorizedProc(authorizedClassA * p)
{ p->Proc(m_instance); }
// 以下許可するクラス分同じコード
private:
Manager m_instance;
};
冗長だし検証してないけど。
212:デフォルトの名無しさん
08/03/23 18:45:30
Manager を使えるクラスを作成する場合には
ファクトリクラスを通すようにする。
で、そのファクトリクラスを friend にして、
そこで Manager クラスを取得して、
各クラスにそれを渡すようにする。
設定関数は各クラスの共通基底クラスに作って、
それをファクトリクラスの friend にする。
213:デフォルトの名無しさん
08/03/23 18:46:54
先輩から聞いたのですが、extern "C" {}せずに構造体を宣言すると、
余計なクラス情報がくっつくって本当ですか?
214:デフォルトの名無しさん
08/03/23 18:52:41
そんなことは聞いた事が無いが、
特定のコンパイラでそういう事があるとかいうんだったら俺は知らない。
215:デフォルトの名無しさん
08/03/23 18:55:11
クラス情報って具体的には何なんだ?
216:デフォルトの名無しさん
08/03/23 18:57:34
>>213
マングリング名にクラス情報がくっつくって話だと思う。
217:デフォルトの名無しさん
08/03/23 18:59:55
>>214-216
言ってたのはシリコンバレー帰りの先輩です
純粋なCの構造体にするにはやはりextern "C"が必要なのですね。
ありがとうございました。
218:デフォルトの名無しさん
08/03/23 19:00:36
>>217
どこからそういう判断をしたんだ?w
219:デフォルトの名無しさん
08/03/23 19:01:52
構造体にextern "C"は関係無いだろ
220:デフォルトの名無しさん
08/03/23 19:02:10
>>216
構造体名って C でそもそも何らかのマングリングされるの?
221:デフォルトの名無しさん
08/03/23 19:07:59
C++なら名前空間やらなんやらくっつくだろ。
222:デフォルトの名無しさん
08/03/23 19:10:41
C で付かないなら
純粋な C の構造体かどうかなんて
どう区別するんだろうか。
223:>>182
08/03/23 19:46:38
>>204
まじめな話、もう一度継承についてちゃんと勉強した方がいいと思う。
(>>205 の内容を理解できてる?)
継承はアクセス制限のためにあるものじゃない。
極端な話、全てが public であったとしても、継承は有用。
これに対して、friend は純粋にアクセス制限を回避するもので、かつ
アクセス制限を回避する以外の機能は無いから、なぜ friend にしたか
がわからなくなることはない。
(もちろん、なせアクセス制限を回避する必要があるかはどっかに書いて
おく必要があるだろうけど。)
>>206
それならアリだと思う。
224:201
08/03/23 19:54:02
>>223
>>205
作られるけど。外から参照されたくないものはpublicにしなけらばいいじゃん
225:201
08/03/23 20:00:37
>>223
>継承はアクセス制限のためにあるものじゃない。
>極端な話、全てが public であったとしても、継承は有用。
だから、継承が駄目なんですか?
継承は色んな意味で使えて「わかりにくい」から駄目ってこと?
226:デフォルトの名無しさん
08/03/23 20:00:37
何かもう駄目だなここって思ったの俺だけだろうか
227:デフォルトの名無しさん
08/03/23 20:02:29
Manager 使ってる部分を別プロジェクトにする。
あとは各クラスのオブジェクト生成を外部から隠せばいい。
228:>>182
08/03/23 21:01:54
>>224
> 作られるけど。外から参照されたくないものはpublicにしなけらばいいじゃん
おいおい、ほんとにもう少し勉強してからこいよ。
引っ込みつかなくなってるだけならいいけど、マジでそう思ってるとしたら
ちょっとまずいよ。
まずい理由の一つは、private でもその変数が見えなくなるわけじゃない、
アクセスできなくなるだけだから。
この違いわかってる?
>>225
> 継承は色んな意味で使えて「わかりにくい」から駄目ってこと?
>>203 に書いたのはそう言うこと。
それしか方法が無いならしょうがないけど、friend と言うもっといい方法があ
るのにわざわざ使わないのは、別の意図があるようにとられる危険性が高い。
229:201
08/03/23 21:17:23
>>228
>マジでそう思ってるとしたらちょっとまずいよ。
Managerを継承していないクラスから参照されたくない場合はpublicにすれば良いって事だよ?
>まずい理由の一つは、private でもその変数が見えなくなるわけじゃない、
>アクセスできなくなるだけだから。
「見える」→メンバ変数の値が取得できる。(getter)
「アクセス」→メンバ変数の値が書きかえれる。(setter)
って意味で言ってるのなら
getter、setter定義してやれば、当然見えるしアクセスも可能。
230:デフォルトの名無しさん
08/03/23 21:42:53
もしかして201氏は、
Managerは1つのクライアント(Managerを使うクラスオブジェクト)の管理のみ引き受けるもので、
クライアントと同数のManagerオブジェクトが必要と考えているのではないだろうか。
231:>>182
08/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:デフォルトの名無しさん
08/03/23 22:11:42
何でこんな残念なスレになってしまったんだ。
233:デフォルトの名無しさん
08/03/23 22:12:43
だって にちゃん だもの
234:デフォルトの名無しさん
08/03/23 22:56:01
VSyncの話したらひどいことになりそう
235:デフォルトの名無しさん
08/03/23 22:57:56
>>231
初心者スレでやれ
ウザイ
236:デフォルトの名無しさん
08/03/23 23:03:27
結局>>182って文句言ってるだけで答えて無いじゃん
237:>>182
08/03/23 23:14:58
答えは >>188 で既にでてるだろ。
まあ、10個ぐらいなら全部 friend 宣言してもいいと思うけど。
もしかして君も >>201 みたいに理解できてないやつなの? (w
238:デフォルトの名無しさん
08/03/23 23:32:29
>>188だとManager::getInstanceみたいなので取得するのと大差無いと思うが・・・
まぁ、それはともかく、>>180にfriendなどを使ってまで
制限する必要性があるのか、疑問だな。
クラスごと使わせなくするとこにfriendを使用している時点でおかしいと思う。
無名名前空間やdetails名前空間で十分なんじゃないか?
239:201
08/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:デフォルトの名無しさん
08/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
08/03/24 00:06:26
>>238
> まぁ、それはともかく、>>180にfriendなどを使ってまで
> 制限する必要性があるのか、疑問だな。
それは、>>180 に聞いてもらわないとダメだけど、そう言う状況はありえると思うよ。
例えば、デバッグのためにマネージャの状態を直接見たりいじったりするクラスとか。
ただ 10個もあるのは、ちょっと多すぎるような気はするけどね。
>>239
頼むから、もう少し勉強してからレスしてくれ。
全然俺の言ってることが理解できてないよ。
242:デフォルトの名無しさん
08/03/24 00:08:40
で、アホなのはどっちなの?初心者なのでよく分かりません
243:デフォルトの名無しさん
08/03/24 00:51:50
>>242
やり方は色々ある。って話に落ち着けていいんじゃないのw
メイヤーズもそんなことeffective c++に書いてたでしょ。
244:デフォルトの名無しさん
08/03/24 05:56:56
>>242
「そいつの中にあるもの」の質はともかく、
「そいつの中にあるものを説明する能力」はどっこいどっこいです。
245:デフォルトの名無しさん
08/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:デフォルトの名無しさん
08/03/24 17:54:22
IX IX
↑ ↑
X IY
↑↑
Y
という継承木になっている。
X::IX::f は定義されているが、
IY::IX::f は定義されていない。
インタフェースクラスを作るなら、IX を仮想継承する必要がある。
ただ、それでも Y で f を定義する必要がある。
あと、インタフェースクラスに限らず、基底クラスには
必ず仮想デストラクタを定義するのを忘れないように。
247:デフォルトの名無しさん
08/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:デフォルトの名無しさん
08/03/24 18:50:40
Y::f では X::f と IY::f のどっちの実装を使えばいいのか分からないというもの。
まあ、今回の場合は IY::f に実装がないから X::f を使いますよという警告だけど、
Y に void f() { X::f(); } と書いておくのが無難。
249:デフォルトの名無しさん
08/03/24 19:06:35
class T
{
T( int );
}
を
T *T_array = new T [100];
は出来ないじゃん?
#placement new使えってのはなしで。
std::vectorはどうやってこういうコンストラクタが引数を持ってるクラスを受け入れてるの?
250:デフォルトの名無しさん
08/03/24 19:07:20
placement newで
251:デフォルトの名無しさん
08/03/24 19:11:33
>>248
上の例では void f() 1個だけですが、実際のIXは純粋仮想関数を
22個もっています。Yに22個の関数をわざわざ定義するのはなんだか
無駄な気がするのですが。。。
252:デフォルトの名無しさん
08/03/24 19:18:29
>>251
まあ、面倒なら今のところは無視してもいいかもしれない。
コメントでも書いとこう。
253:デフォルトの名無しさん
08/03/24 19:26:44
>>241
頼むから、もう少しまともな説明してくれ。
254:デフォルトの名無しさん
08/03/24 19:31:33
>>252
わかりました。ありがとうございました。
255:デフォルトの名無しさん
08/03/24 19:31:46
friend 使うと「一部のクラス」が増えるとManagerも弄らないと駄目だな。
256:デフォルトの名無しさん
08/03/24 19:34:11
拡張性を敢えて犠牲にするなら、個別に friend するしかない。
拡張性もある程度考慮するなら基底クラス作ってそれだけ friend 。
あとは本人がどうしたいか、だな。
257:デフォルトの名無しさん
08/03/24 20:12:41
>>253
非常に初歩的な内容だし、あの説明で理解できないなら、
もうあきらめた方がいいぞ。
258:デフォルトの名無しさん
08/03/24 22:58:50
IDすら出ない板で煽り煽られ大変ですな
259:180
08/03/24 23:04:33
私の為に喧嘩しないで><。
260:デフォルトの名無しさん
08/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:デフォルトの名無しさん
08/03/25 00:06:50
設計?
262:デフォルトの名無しさん
08/03/25 00:07:13
エラーメッセージはキチンと書く
263:デフォルトの名無しさん
08/03/25 00:09:50
;
264:デフォルトの名無しさん
08/03/25 00:11:00
質問の仕方
265:デフォルトの名無しさん
08/03/25 00:11:54
>>263
266:デフォルトの名無しさん
08/03/25 00:11:55
Bにデフォルトコンストラクタないからとか?
267:デフォルトの名無しさん
08/03/25 01:12:43
Humanクラスを基底クラスとするTanakaやAsouやIshikawaクラスがあるとします
Humanは抽象クラスとして用いるつもりです
このときHumanにあるstaticメソッドを一回だけ呼び出したいときってどうすればいいでしょうか?
Humanのコンストラクタで呼び出したとすると、TanakaやAsouのコンストラクタでも呼び出されますよね
static bool initのような変数をフラグとして使う方法は思いついたのですが、
もっとスマートな方法はないのでしょうか?
268:デフォルトの名無しさん
08/03/25 01:16:38
シングルトンやそれに関わるC++の実装は非常に面倒くさくて
自分で一からやろうと思うとどうしても乱雑になる。
マルチスレッドが入ってくるともっと面倒くさくなる。
269:デフォルトの名無しさん
08/03/25 01:25:21
>>260
人生、かな?
270:デフォルトの名無しさん
08/03/25 01:49:26
>>267
そのメソッドを呼び出したいのは、Human派生のオブジェクトを生成したタイミングなの?
271:267
08/03/25 02:13:35
>>270
そうですね
Human派生のオブジェクトを生成する前に呼び出しても構わないのですが
272:デフォルトの名無しさん
08/03/25 02:30:23
>>271
であれば、全てが始まる前に自分で一度だけ呼ぶのが良いと思うな。
273:デフォルトの名無しさん
08/03/25 02:31:52
>>272
それはstaticな変数をフラグにするよりダメじゃねぇかw
274:267
08/03/25 02:39:11
>>272
あぁそうか、そもそもstaticなメソッドなわけだから
int main(){
Human::onlyOnceCalled()
みたいなかんじで
最初の方で適当に呼んでおくってのもありかもしれませんね
一回だけしか呼ばないって保証がないような気もしますが
275:デフォルトの名無しさん
08/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
08/03/25 02:51:47
Human::Initializerのコンストラクタがpublicになってないとか、いろいろダメだorz
そこは適当におぎなって
277:267
08/03/25 03:01:51
>>275
なるほど。こういう方法もあるんですね
勉強になりました
ありがとうございました
278:デフォルトの名無しさん
08/03/25 03:05:20
保証が欲しかったのか。失礼。
initialization orderを気にするならこんな感じかな。
class Human() {
class Initializer {
Initializer() { onlyOnceCalled(); }
public:
static void Initialize() { static Initializer instance; }
};
};
これで、Initializer::Initializeを呼んだタイミングで一度だけ初期化されるようになるよ。ただしこの場合は複数スレッドとかが動き出す前に呼んでね。
279:260
08/03/25 09:32:50
ぇ?コンパイル通る?
gccだと通らないんだけど・・・
280:デフォルトの名無しさん
08/03/25 09:53:30
>>279
どこを見てそう思うんだよ・・・
指摘してくれてるだろ
>>263
>>266
あとAcceptがReturnの返す一時オブジェクトを参照してるから何とかしよう
281:デフォルトの名無しさん
08/03/25 11:14:49
>>279
まずは省略や手抜きをせずに、Bの定義を全部書け。
そして何をしたいのかはっきりさせろ。
282:260
08/03/25 16:02:29
いや、やりたいことは下のやつを知りたかっただけ。
URLリンク(ja.wikibooks.org)(Move_Constructor)
に書いてあることってnon-const referenceを受けるべきとろこに一時オブジェクトを渡せるって話だと思って、
渡してみたらコンパイラ通らないどーん。な状況。
283:デフォルトの名無しさん
08/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:デフォルトの名無しさん
08/03/25 17:14:20
参照渡しから値渡しに変更した理由が分からん
285:デフォルトの名無しさん
08/03/25 17:18:44
抽象クラスのメソッドの定義で質問があります
抽象クラスにおいて、自分自身のクラスへのポインタの引数を取るメソッドは不可能なのでしょうか?
たとえばこういうコードです
class Human {
void foo(Human *human) = 0;
};
コンパイルエラーになってしまいますが、なぜそうなるのか分かりません
抽象クラスだから、インスタンスを作れないので
void (Human human);
のようなメソッドはだめですよね、でもポインタならいけると思うのですが
286:デフォルトの名無しさん
08/03/25 17:20:52
B::operator P()の戻り値から構築されるBの一時オブジェクトは非const参照のAccept(B&)では受け取れないんじゃ?
287:デフォルトの名無しさん
08/03/25 17:23:26
その発送は無かったわ、thisポインタというものが(ry
virtual書いてみたらどうかな?
288:デフォルトの名無しさん
08/03/25 17:27:02
一時変数を値渡しする理由は?const参照にしない理由が分からない。
289:285
08/03/25 17:32:20
>>287
すいません元のコードではvirtualをつけてました
thisポインタは分かるのですが、この抽象クラスを継承したクラスの間でやりとりしたいことがあるのです
不勉強なので間違ってるかもしれませんが、「関連」というのをやりたいのです。
>>285の例でやるなら、一般的にはHumanクラスにHuman *hoge;みたいなポインタをメンバに持たせて関連付けするそうですが
関数の引数でやれないかと思いまして
290:デフォルトの名無しさん
08/03/25 17:35:09
>>288
const参照でもいいかもしれないけど、それ以上所有権を動かせなくならない?
291:デフォルトの名無しさん
08/03/25 17:45:20
Acceptに入ってからも譲渡するなら、
void Accept(B& b) {}
B b = Return();
Accept(b);
の方が良くないかな、それ以前に何のためのPなんだ?
292:デフォルトの名無しさん
08/03/25 17:47:47
>>285
どういう一般的例なのかちょっと分からないけど、
処理と情報を分ける実装の方が個人的にはスッキリするかな
んで、そのプログラムvirtualつけてエラーが出る理由が分からないんだけど…
293:デフォルトの名無しさん
08/03/25 17:49:24
あぁ、失礼した、operator Pはconst守るようにしてるのね
ごめん、俺が悪かった
294:292
08/03/25 18:06:34
>>292
すいませんすごく単純なクラスを作り直し、実験してみると、エラーはでませんでした。
「抽象クラスをインスタンス化することができません」というエラーメッセージだったので、
質問させていただいたのですが、おそらく他のところにエラー.の原因があると思うのでもう一度見直してみます
295:294
08/03/25 18:09:51
>>294の名前欄は>>285の間違いです
296:デフォルトの名無しさん
08/03/25 19:45:31
auto_ptrはauto_ptr_refクラスを介して対処している。
もう知っているかもしれないけど、
C++0xでは非const参照でも一時オブジェクトを受けられるようになる(右辺値参照)。
297:デフォルトの名無しさん
08/03/25 22:07:18
move semantics と rvalue reference &&
298:デフォルトの名無しさん
08/03/25 22:23:46
右辺値参照は何度もこのスレでも話されてるけど理解できん。
299:デフォルトの名無しさん
08/03/25 22:33:41
エラー出る出る言うなら、同じエラーが出る小さいプログラムを示せよ。
BやらPやらの例も、そもそもswapがないでコンパイル止まるしな。
300:デフォルトの名無しさん
08/03/25 22:34:02
右辺値及び左辺値(この二つは組)、参照の理解を固めてから見直すとよろし
301:デフォルトの名無しさん
08/03/25 22:45:08
>>298
簡単に言うと「swapでおk」ってこと。
302:260
08/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:デフォルトの名無しさん
08/03/27 00:31:14
Cの関数ポインタにC++のClassの実体化した関数ていれられますか?
ビルドエラーが出るんですけど、そもそもそんなの出来ない?
304:デフォルトの名無しさん
08/03/27 00:54:49
>>303
できない。
関数ポインタとメンバ関数ポインタは別物。
305:デフォルトの名無しさん
08/03/27 01:38:47
>>303
Windowsのコールバック関数みたいに
こっちから引数を渡せれば、どうにでもできる。
306:デフォルトの名無しさん
08/03/27 01:54:41
>>303
sizeofを使ってポインタサイズを調べてみると、あれびっくりサイズがデカイって分るよ。
どうやっても入りません、キャストしたら情報ロストします。
307:デフォルトの名無しさん
08/03/27 02:00:59
>>306
いろいろ勘違いしてるような。
308:デフォルトの名無しさん
08/03/27 02:24:05
>>307
どこを?
具体的にどうぞ。
309:デフォルトの名無しさん
08/03/27 02:29:53
>>304-306 のうち確実に間違っているのは >>305 です、要注意。
310:デフォルトの名無しさん
08/03/27 02:49:53
面倒だからboost::functionを調べてみ >303
311:デフォルトの名無しさん
08/03/27 02:56:20
詳しく説明した方がいいかと
要するに、メンバ関数ポインタがさす関数はvirtualである事もあって
インスタンスに仕込まれた仮想テーブルを参照して、関数テーブルのうちどの位置にあるものかを取得する必要がある。
また、関数はvirtualでないケースもある、この場合仮想テーブルには関数のアドレス情報はないので、関数メンバポインタ内に情報がなければならない。
関数メンバポインタはこれら複合情報で構成された構造体となっている。
312:デフォルトの名無しさん
08/03/27 03:03:53
どこが詳しいのか
313:デフォルトの名無しさん
08/03/27 06:03:12
それなりに詳しいと思うけど、
であるがゆえに「要するに」から始まっているのは間違いだと思う。
314:デフォルトの名無しさん
08/03/27 07:26:14
>>303
関数ポインタには入れられないが、
実体とメンバ関数ポインタの対を構造体にしたものを引数に取る
ラッパ関数を通して呼ぶことはできる。
もちろん、C 側ではその構造体を直接扱うことはできないから、
void * を通すなり不完全型を利用してポインタで扱うなりする必要はあるけど。
315:デフォルトの名無しさん
08/03/27 07:39:53
>>309
>>305はCのライブラリのコールバック使うときとかの対処法の話じゃね?
大抵はvoid*のパラメータ持ってるし。
316:デフォルトの名無しさん
08/03/27 07:46:12
virtual関係無いよね。
317:デフォルトの名無しさん
08/03/27 08:15:45
そもそも、C++のclassの実体化した関数って何?実体化って何を言ってるんだ
インスタンス増えたら関数も増えるとか思ってるのだろうか、理解に苦しむ
URLリンク(www.microsoft.com)
318:303
08/03/27 08:50:26
やりたいのは複数newしたクラスからCの関数叩くんですけどその時の引数にコールバック用のCの関数ポインタがあるんです
そしてその時呼んだ実体に関数ポインタによって帰ってくるようにしたいんです
319:デフォルトの名無しさん
08/03/27 09:03:26
引数を加えて、static関数で良いんじゃ?
320:デフォルトの名無しさん
08/03/27 09:20:50
>>317
非staticメンバ関数/インスタンスメソッドの事だとみんな理解してるよ。
>>318
コールバック関数のパラメタを汎用ポインタとかで指定できるなら、そこにオブジェクトのアドレスを入れて、コールバック関数内でキャストしてメンバ関数を呼ぶ。
パラメタを指定できないなら、コールバック関数から見えるスコープの変数にオブジェクトのアドレスを入れておき、コールバック関数からメンバ関数を呼ぶ。
321:デフォルトの名無しさん
08/03/27 10:10:15
クラスの関数ポインタはthisが略されてるようなもんじゃね
322:デフォルトの名無しさん
08/03/27 10:31:11
>>317
往生際が悪い、素直に自分の知識不足でしたと認めろ
323:デフォルトの名無しさん
08/03/27 11:13:55
>>317
そのあたりは処理系依存だろ
324:デフォルトの名無しさん
08/03/27 13:09:21
static メンバ関数を C のコールバックに登録するのってよく見るし実際に
やったこともあるんだけど、ほんとは extern "C" と extern "C++" の違いで
型が遭わないはずなんだよね。
だからって対応策がわかんないし、使ったことのあるコンパイラでは全部通るから
そのまま使っちゃうんだけどさ。
325:デフォルトの名無しさん
08/03/27 13:35:22
>extern "C" と extern "C++"
"C" とかの修飾は、識別子を外部にどういう規則で公開するかという点についての指定であって、スタックフレームの作り方の指定ではない。
機種依存なので、そっちにいけと事になるが、cdeclとpascalが違えば "C" を付加しても動作しない。
C型のスタックフレームを持つ関数として登録可能な関数なら、C型のコールバックに登録する事ができるという事。
そうでないなら、コンパイルが通ったとしてもうまくいかない。
326:デフォルトの名無しさん
08/03/27 13:52:21
>>325
スタックフレームとか実装に立ち入った話はしてない。言語概念上の型が違うんだよ。
327:デフォルトの名無しさん
08/03/27 13:53:59
>>326
力いっぱいデタラメぶちかまさない
328:デフォルトの名無しさん
08/03/27 13:58:42
知識不足は許容できるが嘘吐きになってはイカンぜよ
329:デフォルトの名無しさん
08/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 でもバグ扱いだ。
URLリンク(gcc.gnu.org)
330:デフォルトの名無しさん
08/03/27 14:06:37
>>329
自分を嘘と虚栄で塗り固めるような真似はやめた方がいい、どこに突っ込み入っているのかすら理解できていないだろ。
331:デフォルトの名無しさん
08/03/27 14:10:44
静的メンバ関数はextern "C++"ではない
332:デフォルトの名無しさん
08/03/27 14:11:10
328は327に宛てたもんだと俺は思った、どうでもいいけど。
333:329
08/03/27 14:11:40
>>330
ごめん。どこに突っ込み入っているのかすら理解できてない。
どこが嘘になってるの?
334:デフォルトの名無しさん
08/03/27 14:16:32
>>331
何を根拠にそんなこと言うのか知らないけど、じゃぁ静的メンバ関数の
language linkage は "C++" 以外の何になるのさ?
335:デフォルトの名無しさん
08/03/27 16:56:26
虚言癖というか妄想癖というか・・・なんかもう病気だね(汗
336:デフォルトの名無しさん
08/03/27 17:04:34
>>334
静的メンバ関数のリンケージは内部リンケージで
その根拠は外部に公開されないから
逆にextern "C++"と同じという根拠は?
337:デフォルトの名無しさん
08/03/27 17:05:02
もうv(^・^)vの人はいないの?
338:デフォルトの名無しさん
08/03/27 17:20:53
ちゃんと勉強しろ、そんな高度な話題じゃねぇよ
339:デフォルトの名無しさん
08/03/27 18:55:41
コンストラクタの中で
配列宣言しているオブジェクトの
コンストラクタ引数を設定するにはどうしたらいいですか?
340:デフォルトの名無しさん
08/03/27 19:03:37
class Test{
Test0 objects[10];
...
};
Test::Test()
:objects[0]( 10 )
,objects[1]( 8 )
...
{
}
こんなかんじをやりたいのです。
もちろん、これではエラーです
341:デフォルトの名無しさん
08/03/27 20:36:48
>>339
できないよ。
342:デフォルトの名無しさん
08/03/27 20:51:07
解答を待っているのかもしれないが、本当にできないから。
URLリンク(www.geocities.jp)
343:デフォルトの名無しさん
08/03/27 20:57:51
どうしてもそれっぽいことがやりたいなら
vector<Test>にひとつひとつpush_back()するか
ポインタの配列にしてひとつひとつnewすればいいんでないの
344:デフォルトの名無しさん
08/03/27 21:55:56
VC++6で
for(int i=0; i<10; i++){
...
}
for(int i=0; i<10; i++){
...
}
って書いたら
iの再定義っておこられた
拡張子cppになってるのに
345:デフォルトの名無しさん
08/03/27 21:57:25
仕様です
346:デフォルトの名無しさん
08/03/27 21:58:46
1998年発売のソフトやもん。
347:デフォルトの名無しさん
08/03/27 21:59:23
>>344
びっくりするくらいみんな知ってる。
規格準拠していないんだから何も問題ない。
348:デフォルトの名無しさん
08/03/27 22:01:35
>>344
#define for if(0); else for
魔法のおまじない
349:デフォルトの名無しさん
08/03/27 22:01:59
当時は準拠してたんだよ
350:デフォルトの名無しさん
08/03/27 22:03:21
まだ規格もなかったのに何に準拠してたというのか。
351:デフォルトの名無しさん
08/03/27 22:04:00
常識。
352:デフォルトの名無しさん
08/03/27 22:29:04
>324,329
だいたい、「関数ポインタ型」それ自体にはリンケージなんか無いだろ。
それともこーゆーコードが通るコンパイラでもあるのかっつーの。
typedef static void (*hoge)();
typedef extern void (*foo)();
typedef extern "C" void (*var)();
353:デフォルトの名無しさん
08/03/27 22:36:23
typedef void (*__stdcall type)();
こういうのならたまにやる。
354:デフォルトの名無しさん
08/03/27 22:36:46
それはリンケージじゃなくて呼び出し規約
355:デフォルトの名無しさん
08/03/27 22:48:31
>>350
ARM、ISOのドラフト
356:デフォルトの名無しさん
08/03/27 22:49:53
>>355
>>344 なていたらくでか
357:デフォルトの名無しさん
08/03/27 22:58:27
>>356
forの中で定義した変数の有効範囲が
直後のループ本体に限られるようになったのは
結構遅かったのでは?D&Eでも軽く触れられていたし。
それに加え過去の互換性のためVC6はあれがデフォルトになったんだと思う。
358:デフォルトの名無しさん
08/03/27 23:27:37
昔の人が考えた仕様には、頭おかしいだろうってのがそれなりに有るからね。
359:デフォルトの名無しさん
08/03/27 23:47:27
初期のコンパイラの実装の都合もあったんじゃないかな?
最近のコンパイラで、forの変数の有効範囲が限られるようになってるのに最近気づいて思わずGJと叫んだ。
360:デフォルトの名無しさん
08/03/28 00:10:34
>>357
まあ 1998 年と言えば規格が出る年だしな。
開発期間とか考えると多少前の仕様に準じようとしてたと考えるのが妥当だけど、
その時期ならドラフトとはいえかなりな部分まで練られてると思うんだけどな。
まあ、想像でしかないので本当にギリギリになって入れられた仕様なのかもしんないけど。
VC6 はテンプレートまわりがバグ持ちすぎてかなり酷いが、
テンプレートも遅くに入った仕様だからな・・・。
new がデフォで bad_alloc 投げないとか、とにかく色々と酷い上に、
しばらく次のコンパイラが出なかったという・・・。
361:デフォルトの名無しさん
08/03/28 00:18:58
未だに古いライブラリとかで使わないといけないことが結構あるからねぇ
VS2005から入った俺としては結構苦痛
まあでもテンプレートさえなければインテリセンス反映が早いのはよい
362:デフォルトの名無しさん
08/03/28 00:36:24
VC++6.0は当時の状況を考えればしょうがないと思う
問題なのは次のコンパイラがさっさと出なかった事
お陰で変に普及しちまって、このスレでもVC++6.0でコンパイルできません的な質問が絶えない
363:デフォルトの名無しさん
08/03/28 00:38:12
全てはMSが次期製品を確実に買ってくれる為に図った陰謀。
364:デフォルトの名無しさん
08/03/28 00:53:13
MSの事情的にはむしろ逆のような?
過去のシステムヘッダに, for で宣言した変数が
その後も生きることに依存したコードがあったっていう……
365:デフォルトの名無しさん
08/03/28 00:56:00
#define for if(0) else for
のおまじないと使ったあとでATLをincludeすると
怒られるちゅーか
366:デフォルトの名無しさん
08/03/28 01:14:53
>>363
そして満を持して登場した 2002 が糞だったという罠。
そして 2003 で大きく改善されるという二重の罠。
アカデミックだと無料アップグレードできないという三重の罠。
367:デフォルトの名無しさん
08/03/28 01:16:50
#define for if(0); else for は色々やった後にやるとよろし。
368:デフォルトの名無しさん
08/03/28 01:55:57
ってかincludeする前にundefするだろ・・・
369:デフォルトの名無しさん
08/03/28 02:11:01
>>336,352
ややこしくて嫌になるが、内部とか外部とかがある「リンケージ」と
"C" とか "C++" とかがある「言語リンケージ」("language linkage") とは
別物。 >324,329 が言ってるのは言語リンケージのほうなんで、話がまるで
かみ合ってない。
370:デフォルトの名無しさん
08/03/28 03:12:43
自信満々な>>336が可哀想に見えてきちゃったよw
逆にextern "C++"と同じという根拠は?ってのが哀愁をソソル
371:デフォルトの名無しさん
08/03/28 03:26:11
>>336
素の「リンケージ」の話だとしてもおかしい。静的メンバ関数のリンケージは
ほとんど外部リンケージになる。例外は関数内のクラスのメンバの場合とかね。
372:デフォルトの名無しさん
08/03/28 03:29:08
静的メンバ関数が「外部に公開されない」ってのもおかしいな。
クラスの宣言されたスコープや、クラス内での private なり public なりに
従うだろ、常考。
373:デフォルトの名無しさん
08/03/28 03:50:38
びやーんはもうC++なんか使っていないらしい。
374:デフォルトの名無しさん
08/03/28 05:40:45
ソースは?
375:デフォルトの名無しさん
08/03/28 07:19:26
2ch
376:デフォルトの名無しさん
08/03/28 08:03:31
>>372
public, privateと内部リンケージ, 外部リンケージはまた別の話だ
377:デフォルトの名無しさん
08/03/28 08:07:53
もう何がなんだかわからないよママン
378:デフォルトの名無しさん
08/03/28 09:26:26
>>359
もともとがCへのトランスレータだった事を考えれば自然に合点が行くね。
for( int i = 0 ; .... ) { ... }
変換後
{
int i ;
for( i = 0 ; .... ) { ... }
}
379:デフォルトの名無しさん
08/03/28 09:47:14
>>377
C++の仕様書を見ればいいと思うお
380:デフォルトの名無しさん
08/03/28 09:57:02
>>372
リンカなどの外部に公開され得るのはクラスであって内部リンケージであるメンバが同様に公開されているように見えるのは処理系の都合
381:デフォルトの名無しさん
08/03/28 11:33:58
>>380
クラスが外部リンケージを持つときに、メンバ関数が外部リンケージを持つかどうか は処理系依存だと言っているのならそれは違うよ
382:デフォルトの名無しさん
08/03/29 03:01:24
>>377 >329,324
383:デフォルトの名無しさん
08/03/30 01:04:01
テンプレートをつかうと一気にコンパイル時間が10倍に?!
384:デフォルトの名無しさん
08/03/30 01:07:31
>>383
>>5
385:デフォルトの名無しさん
08/03/30 15:11:26
template使っても
型が1個と100個じゃ大違いだろ
386:デフォルトの名無しさん
08/03/30 15:17:08
このテンプレいつの間にか一つのレスにまとめられてたのかw
387:デフォルトの名無しさん
08/03/30 15:27:00
template <typename Questioner>
int IsCompileTimeBecomeLongerByUsingTemplate() {
return ENVIRONMENT_DEPENDENT;
}
388:デフォルトの名無しさん
08/03/30 16:25:46
テンプレート無意味過ぎる
389:デフォルトの名無しさん
08/03/30 16:28:21
>>388
質問者に応じて別の回答をするように特殊化するんだよ。
次ページ最新レス表示スレッドの検索類似スレ一覧話題のニュースおまかせリスト▼オプションを表示暇つぶし2ch
4575日前に更新/200 KB
担当:undef