トップページ⇒tech
1001コメント302KB

C++相談室 part34

■ このスレッドは過去ログ倉庫に格納されています
0001v(^・^)vNGNG
C++に関する質問やら話題やらはこちらへどうぞ。
ただし質問の前にはFAQに一通り目を通してください。
テンプレートライブラリ(STL含む)に関する質問は
専用の別スレにお願いッス。

過去スレ、関連スレ、関連リンクなどは >>2-20 あたり
0756デフォルトの名無しさんNGNG
>>751
スレの書き方・質問の仕方から察するに、プログラマに向いてない。
それが一番の問題。巻き添えを食うであろう同僚PGが気の毒。
0757デフォルトの名無しさんNGNG
>>755
なんだと
0758デフォルトの名無しさんNGNG
>>751
こりゃまた強引なネタで C++ の話題に戻しにかかってきたねぇ・・・
もしネタじゃないなら、ネタじゃありません、とか書いておいた方が良いよ。
0759751NGNG
>>754
そうなんですか?
なにがおかしいのでしょう。

>>758
C++の話題に戻すのが目的でもありませんし、ネタでもないのですが
なにがおかしいのか教えていただけませんか?

みなさんのレスから想像すると、何か変なこと聞いてます、俺?
0760デフォルトの名無しさんNGNG
SampleClass sclass();
これは関数宣言
0761デフォルトの名無しさんNGNG
>>756
この書き方は何が問題なの?
0762デフォルトの名無しさんNGNG
Exceptional C++ 項目42参照
0763デフォルトの名無しさんNGNG
>>756のような態度を取る奴の同僚PGの方が、オレは気の毒だと思うな。
0764デフォルトの名無しさんNGNG
省略時コンストラクタがないクラスで
operator new
std::get_temporary_buffer
どっち使うのが主流?
0765デフォルトの名無しさんNGNG
>>761
756 じゃないけど「・・・と思った」とか「納得いかない」っていうのは、
自分でアレコレ調べてみる動機としては結構だけれども、
単に「・・・と思ったけど違った。納得がいかない」っていう質問はちょっとアレだろ、
訊かれたほうも困るだろ、ということでは?

>>751-752
ちなみにエラーの意味はだいたいこんなところ。

(1) エラー
非集合体の型 'SampleClass ()()' として定義された 'sclass()' に対して
メンバ 'action' が要求されました。

(2) エラー
非集合体の型 'UserClass()(SampleClass (*)())' として定義された
''uc(SampleClass (*)())' に対してメンバ 'doAction' が要求されました。
0766751NGNG
レスしてくれたみなさんありがとうございます。

>>760
あ、言われてみればそうですね。
ということは>>753のいう奇妙な解析というのはこれのことだったのですね。
実引数の無い時は関数宣言と解釈されるから、そのときは特別扱いで
空の括弧はなし、と。

ということは(2)に関しても
UserClass uc(SampleClass());
SampleClass()という関数として解釈されてるということでしょうか?
しかし、次の行のuc.doAction()をコメントアウトするとコンパイル&実行
できます。ただし、SampleClass::SampleClass()は呼ばれていないようです。

こちらはどういうことなんでしょう。

>>762
(More) Effective C++なら持っているんですが、その本は持っていません。
明日大至急立ち読みしてきます。
0767デフォルトの名無しさんNGNG
>>766
UserClass uc(SampleClass());
これは 引数 void、関数値 SampleClass の関数へのポインタを引数に取る関数の宣言だ

(More) Effective C++ 持ってるのに分からないなんて終わってるなお前
0768デフォルトの名無しさんNGNG
>>766
uc っていう関数として認識されてる。この関数の型は UserClass()(SampleClass (*)())
SampleClass を返す引数無しの関数ポインタを引数とする、UserClass を返す関数。
型の記述を読めるようになった方が良いよ。
0769751NGNG
>>765
エラーメッセージの意味ありがとうございます。

>>767, 768
なるほど、やっと理解できたようです。
たしかに型の記述が読めてないですね、精進します。
0770デフォルトの名無しさんNGNG
>>764
配置new…かな?
0771デフォルトの名無しさんNGNG
>>764
何をするためにそいつら使うの?
0772デフォルトの名無しさんNGNG
class Test
{
char a[10];
int b;
char c[5];
public:
func();
};

こんな感じのクラスがあったとします。
これのインスタンス class Test test;
を定義して、例えば char c[5]
の先頭アドレスを取得したいんですが、
良い方法はないですか?
0773デフォルトの名無しさんNGNG
>>772
class Test
{
char a[10];
int b;
char c[5];
public:
func();
char* get_address(int i) { return c + i; }
};

Test test;
char* p = test.get_address(5);
0774773NGNG
>>773 すまん、忘れて。
0775デフォルトの名無しさんNGNG
>>772
C++のクラスでもoffsetofマクロがそのまま使える。調べてみるべし。
0776デフォルトの名無しさんNGNG
>>775
先頭アドレスってそういうことだったのか?読みが深いな。
0777772NGNG
>>773
>>775
ありがとうございます。調べてみます。
0778722NGNG
offsetofの一定義例によると、求められたオフセット値はsize_t
にキャストされているマクロになってました。
>>772のc[5]のアドレスを指定されてそこに書き込む関数、
を考えると

static Test test;

SetAAA(const char *str)
{
Test* p;
size_t offset;
char* dest;

p = &test;
offset = offsetof(Test, c);
dest = p + offset;
strcpy(dest, str);

}
のような事をしたいのですが、この場合、安全なキャスト
はどのようになりますか?

dest = (char*)(p+offset);

と強引にやってしまってよいでしょうか?
0779デフォルトの名無しさんNGNG
>>778
C++を使うなら(char *)とやらずにreinterpret_cast<char*>(p + offset) と書くべき。
働きは変わらないが。
0780デフォルトの名無しさんNGNG
しかしなぁ、メンバへのポインタを使った方が楽だと思うんだけど。
まあいいけど。
0781デフォルトの名無しさんNGNG
>>780
メンバへのポインタはアドレスじゃないから、>>778への最適解にはならんな。
実際内部クラスへの委譲をするにはメンバへのポインタではなくoffsetofマクロ
を使ってアドレスを求める必要があるしな。ケースバイケースかな。
0782デフォルトの名無しさんNGNG
offsetofを使ったこと無いやつばっかだな・・・実際、あまり使うこと無いけど。

offsetofを使ってメンバのアドレスを求めるときは、
まずchar *にキャストしてそれからoffsetを加え、さらに実際のメンバの型にキャストするから
えらい汚くなるのよん。

dest = reinterpret_cast<char*>(p + offset);
じゃ正しく動かないねん。
0783デフォルトの名無しさんNGNG
for( iterator i = begin(); i != end(); ++i )
i->m_p = NULL;

これを「for_each」を用いた式に変更したいんですが
出来るでしょうか?


0784デフォルトの名無しさんNGNG
関数オブジェクトを作って使う
0785デフォルトの名無しさんNGNG
class Test
{
char a[10];
int b;
public:
func();
char c[5];
};

Test test;
char *p = test.c;
ところでこれじゃだめなのか?
0786デフォルトの名無しさんNGNG
for_each(begin(), end(), bind(&T::m_p, _1) = NULL);
とかか?
0787デフォルトの名無しさんNGNG
>>784,>>786
mem_func1をパクってmem_assignを作りました。
ありがとうございました。
0788デフォルトの名無しさんNGNG
Class Hoge{
private:
 int hage; //他メンバ変数が「20」個
public:
 void func( int n ){
  switch(n){
   case CASE0: hage達に関する複雑な処理; break;
   case CASE1: hage達に関する複雑な処理; break;
   //以下延々と「30」個
  }
 }
};
case文が多いので、そこの処理だけを他クラスに切り分けたいと思ったのですが(Stateパターン?)、
切り分けたクラスからHogeのメンバ変数であるhage達にアクセスする良い手段は無いでしょうか。
 ・getter/setterを20個ずつ用意する
 ・friendを30行書く
 ・メンバ変数を全て構造体にまとめ、切り分けたクラス達に渡す
思いついたのは、どれもいまいち _| ̄|○
0789デフォルトの名無しさんNGNG
内部クラスにしてfriend
0790デフォルトの名無しさんNGNG
>>788
・必要なメンバ変数に相当するものを構造体にまとめ、切り分けたクラス達に(getter, setterで)渡す
に1票。インタフェイスが明確になるし。
0791デフォルトの名無しさんNGNG
vimでvi使うのってどうやるの?
0792デフォルトの名無しさんNGNG
:set compatibleじゃ内科?
スレ違い
0793デフォルトの名無しさんNGNG
>>789-790
レスありがとうございます。
やはりそういうやり方(俺のより遙かに洗練されてますが)しか無いのですね。

リファクタリングの本なんか見ると、switch-caseは全てstateパターンに
しろと言いかねない勢いで記されていますが、こういう風に分けなければとなると、
かえって解りづらい気がしてしまいますねぇ・・・。
0794デフォルトの名無しさんNGNG
stateパターンに移行できるようなinterfaceで設計しておけばいいんと違う?
0795デフォルトの名無しさんNGNG
cygwinにgcc3.4.1が入ったので使ってみた。

「参照されないstatic変数・関数は削除される」という変更が入っているらしいので、
早速試してみたところ、たしかに削除された。
 static int x = 0; // この定義に対する領域の確保は無い

ふと思い立って、無名名前空間に置き換えたところ、変数領域の確保が出力された。
 namespace { int x = 0; } // この定義に対する領域が確保される

無名名前空間によるファイルローカルな変数・関数は、
staticと同様に参照されない場合に削除してはいけないのでしょうか?
0796デフォルトの名無しさんNGNG
素人な漏れから見れば、static が削除されるのなら無名名前空間も削除されてしかるべきなように思えるが…
0797795NGNG
調べてるうちに、この問題についての議論を拾ったので貼っておこう。
ttp://gcc.gnu.org/ml/gcc/2004-01/msg02323.html
ttp://gcc.gnu.org/ml/gcc/2004-01/msg02341.html
gcc開発者側の言い分を勝手に要約すると、
「無名名前空間がstaticのかわりに使えるようにしたかったのは分かるが、
 現状の規格に従う限りそれらは意味的に違うものになってしまっている。
 最適化のために規格に則ったプログラムを犠牲にするわけにはいかない。
 今までどおりの"static"として扱って欲しいのなら、"static"と書け。」
という感じ。
gccの現在の実装を盾にしている感もあったのだが、
ソースを見ずしてそこを非難するわけにはいかない。

ついでに、標準委員会の関連する動きも貼っとく。
ttp://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#223
ttp://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#167
ttp://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#174
cwg_active.html#223 ってのが最悪で、
「deprecatedだからどうなの?」っていう話が未だに決まってないらしい。
激しく萎えた。
0798デフォルトの名無しさんNGNG
別に削除されてもされんでもどうでもいいとオモタ
0799デフォルトの名無しさんNGNG
std::localeあたりに削除されてほしいstatic変数がいくつかあるが
きれいに消えるんだろうか?
0800デフォルトの名無しさんNGNG
消えてもせいぜい50kBくらいじゃないの?
消えたからって特になんの効果もなさそうな気が。
0801デフォルトの名無しさんNGNG
>>800
処理系によっては、いくつか main() 走る前にコンストラクタが動いて、
動的メモリ割当を行うオブジェクトがあったりする。メモリ管理に手を
入れる場合に、ひじょーに面倒臭い。
0802デフォルトの名無しさんNGNG
>>801
そんなオブジェクトも削除されるのか?
0803デフォルトの名無しさんNGNG
単なる関数ポインタ宣言なら「void (*pf)();」と書けますが、

「A」というクラスに「B()」というメソッドがあった場合の、
Bのポインタ変数の宣言を教えて下さいでつ。
0804デフォルトの名無しさんNGNG
A::*B
0805デフォルトの名無しさんNGNG
>>803
void B(); なら void (*A::f)();
0806デフォルトの名無しさんNGNG
>>805
あ、*の位置間違えた、と思ったら >>804 が書いてた。
0807デフォルトの名無しさんNGNG
今更ながらの質問なのですが、効率的なincludeの仕方ってあるんでしょうか?

例えばhoge.cppとhoge.hが共に、stdhoge.hを必要とする場合
hoge.hの先頭に#include<stdhoge.h>する方法と
hoge.cppの先頭に、stdhoge.h>hoge.hの順で#includeする方法がありますが・・・。

後者は他でhoge.hを使う場合にも同順でやらなければと不便で、今まで避けていましたが、
世のライブラリを見ると、特定の順序でincludeせよという物も多く、疑問に思った次第です。
0808デフォルトの名無しさんNGNG
普通両方でインクルードするんでは?インクルードガードしてないと
おかしなことになるだろうし、してあればコードの解釈は1回ですむ
からそこまで効率が落ちるってことはないだろうし。
0809デフォルトの名無しさんNGNG
>>807
ファイルは単独で意味を持つ方が望ましいという観点から見ても、前者がいい。

>世のライブラリを見ると、特定の順序でincludeせよという物も多く、疑問に思った次第です。
標準ライブラリがそうでないように、そういう注文を付けるライブラリは怠慢だと思う。
0810デフォルトの名無しさんNGNG
hoge.hをインクルードしたらstdio.hの関数が使えるってのは嫌な話だ。
0811デフォルトの名無しさんNGNG
>>810
C++スレでそんな事を嘆くべきかな?
テンプレートが記述されたヘッダをインクルードする時に、
避けられないことだと思うけどなぁ。
0812デフォルトの名無しさんNGNG
exportつかいてえ
0813デフォルトの名無しさんNGNG
関数ポインタを引数に持つCライブラリ関数に、
C++のstatic宣言されていないメンバ関数を渡して、
実行させることはできますか?

staticでないC++のメンバ関数の実行には、仮想関数など
ランタイム時に決定される種類のものがある。だから、
Cライブラリ関数がそれを関知して動作することは不可能
→ゆえにstaticしか通らない。

と考えているのですが。

0814807NGNG
皆さんレスありがとうございます。
とりあえず唯一解みたいのが無くて安心しました。。

>>808
私の使っている駄目なIDEだと、cppの方にincludeしてないと
入力補助が働かないので、実利の面からその考えは納得できます。

>>809さんのレスが、最も同感です。
ちなみに私が悩んだライブラリの筆頭がWTLです。

>>810-811
それもまた、もっともですよね…。かなり嫌ではあります…が。
0815デフォルトの名無しさんNGNG
>813
概ねその通り。

まあ、渡せない理由は
仕様的には、型が違う
実装的には、暗黙のthisが引数に含まれる
からだけどな。
0816デフォルトの名無しさんNGNG
>>813
仮想関数などを使っていなくても、C 風の関数ポインタは
"this"が何であるのかっていう情報を持っていないので、
C風の関数ポインタを用いてメンバ関数を呼び出すことは出来ません。
0817デフォルトの名無しさんNGNG
>>813
プログラミング言語C++ 第3版 15.5
> メンバポインタは、変数ポインタや関数ポインタとは異なり、
> メモリの位置を指すポインタではない。
> メンバポインタは、ポインタというよりも構造体オフセット、
> 配列の添え字に近い。
0818813NGNG
みなさんすみません。

最初、スレッドの初期化等を抽象化する基底クラスを
用意し、派生クラスではrun()メンバ関数のみを実装
すれば、コンストラクタ内部で自動的に
pthread_create(..., run, ...);
が呼ばれてスレッドが生成される...みたいな
スレッドライブラリを考えていたのですが....

スレッド生成はWin32ならbeginthreadex_だし、
Linuxならpthread_createだしで、けっこう相違が
あるので、隠蔽したいんですよ...。
どういう設計にするのが妥当でしょうか?

いままでCだけで書いて来たので、実際に応用しようと
するといろいろわからないことが...
0819デフォルトの名無しさんNGNG
>>818
スレッドで実行される関数に少なくともポインタが格納できるサイズのパラメータが渡せるはずだから、
そこに this を reinterpret_cast して渡してあげて、スレッドの開始関数 (static) では単に

static int ThreadProc(..., void* arg)
{
 return reinterpret_cast<ThisClass>(arg)->run();
}
0820デフォルトの名無しさんNGNG
>return reinterpret_cast<ThisClass>(arg)->run();
return reinterpret_cast<ThisClass *>(arg)->run();
0821デフォルトの名無しさんNGNG
>>818
どうでもいいけど、スレッドのクラスによるカプセル化は止めた方がいいよ。
ま、C中心だったのであれば、潔癖なカプセル化はしないだろうけど、念のため。
0822デフォルトの名無しさんNGNG
>>818
> スレッド生成はWin32ならbeginthreadex_だし、
> Linuxならpthread_createだしで、けっこう相違が
> あるので、隠蔽したいんですよ...。
差異の吸収はboostにやらせるのはどうでしょ?
0823デフォルトの名無しさんNGNG
>821
そうなの?漏れけっこうガチガチにカプセル化しちゃたけど
特に不便を感じた事はなかったな。。。
>818みたいに,いろんな場所で動かす事を考えると
大変になるって事?
それとも漏れのカプセル化がまだユルユルだったのかな。
0824813NGNG
うう、819さんのおっしゃることが理解できないんです。
すみません。
reinterpret_castを使ったスレッド生成関数の
startup_routineを作っても、pthread_createや
親クラスへもっていく方法がわかりません。

#include <stdio.h>
#include <unistd.h>
#include <pthread.h>

class Thread {
public:
 virtual int run(void *) = 0;
protected:
 pthread_t t_;
};

class TSub : public Thread {
public:
 TSub();
 int run(void *);
protected:
};

static void * stub_thread(void *pParam)
{
 reinterpret_cast<Thread *>(pParam)->run(pParam);
 return NULL;
}
(つづきます)
0825813NGNG
TSub::TSub()
{
 pthread_create(&t_, NULL, stub_thread, (void *)this);
}

int TSub::run(void *pParam)
{
 sleep(3);
 return 0;
}

我ながら....情けなくなるのですが、TSubのコンストラクタに
書いてある内容をThreadのコンストラクタかメンバ関数に
もっていきたいわけです。
0826813NGNG
ちなみに今まではUNIX/Win32でほぼ1vs1になるように
スレッドAPIを#defineで再定義していました。返り値なども。

ただ、スレッドプログラミングを進めるにつれ、
スレッドが使うヒープなどを終了時に自動的に回収したいとか、
pthreadそのままなのでprimitive過ぎて使いにくいとか、
いろいろ不満がでてきたのです。

Boost、恥ずかしながら今初めて聞きました。
ドキュメントを読んでみようと思います。
0827デフォルトの名無しさんNGNG
こうかな?
class Thread {
public:
 int Start()
 {
  return pthread_create(&t_, NULL, stub_thread, reinterpret_cast<void *>(this));
 }
 int Join(void** value_ptr = 0)
 {
  return pthread_join(t_, value_ptr);
 }
protected:
 static void * thread_func(void *pParam)
 {
  Thread *pThis = reinterpret_cast<Thread *>(pParam);
  return pThis->run(pParam);
 }
 virtual int run(void *) = 0;
protected:
 pthread_t t_;
};

class TSub : public Thread {
public:
 TSub();
protected:
 int run(void *) { sleep(3); return 0; }
};
0828デフォルトの名無しさんNGNG
上の
return pthread_create(&t_, NULL, stub_thread, reinterpret_cast<void *>(this));
の stub_thread は thread_func の間違い。

ただ、今から書くのならば
class IRunnable {
public:
 int run() = 0;
};
みたいなのを単独でインタフェイスとして定義して、Thread クラス本体と run を実装する
クラスを分ける方がよいと思う (Thread::Start の引数として IRunnable* を取る)。
0829813NGNG
>>828
キタ━━━━(゜∀゜)━━━━!!
最初思っていたことは上記のコードでできそうです。
ありがとうございました。

で。IRunnableの話なのですが、Thread I/Fとして
のclass Threadから、run()を追い出すとどのような
メリットがありますか?

まずThreadクラスのインスタンスを生成/管理する
ThreadFactoryとかThreadPoolとか作っておいて...

それらとは別に作っていたクラス
(例えばScreenManagerとか)で、値の監視的要素が
出てきたら、おもむろにIRunnableをくっつけて
run()だけ実装して、
ThreadFactoryに「スレッドにdispatchしてくれ」と
頼む、みたいな感じでしょうか。Start()が参加で、
Join()が脱退みたいな。
0830デフォルトの名無しさんNGNG
ここは頻繁にカプセル化するな厨が現れるな。
0831デフォルトの名無しさんNGNG
プログラムの規模によるんだよ
0832デフォルトの名無しさんNGNG
ThreadとかWindowとか、OSの機関にかかわる部分や特有の機能はカプセル化するべきじゃない。
Socketとかコンソールとか、どのOSでも似たような機能を備えていそうなものだけカプセル化するべきだ。
0833デフォルトの名無しさんNGNG
>>832
グローバル変数はアプリケーションインスタンスの
インスタンス変数って考え方でいいじゃん。
あとアクセス制御をどうするかって論点に絞るだけ。
0834デフォルトの名無しさんNGNG
カプセル化の是非はOOスレでやれ。
ここはC++でどうやるのがいいか悪いかを論じる。
0835デフォルトの名無しさんNGNG
>832
ポータビリティを重要視したライブラリを真っ向から否定ですか?
0836デフォルトの名無しさんNGNG
>>832
プラットホーム間のポータビリティとは限らんでしょ。
スレッドやソケットはさすがに微妙だと思うよ。
もろシステムコールじゃん。明らかに他のジャンルと異質。
0837デフォルトの名無しさんNGNG
>>835
ポータビリティはOSの特色を生かせない低賃金がする言い訳
個々のOSの特徴や性能を100%引き出してこそプロ
0838プッNGNG
CとかC++とかperlとか、
ポータビリティのある言語だからプロ向けじゃ(ry
0839デフォルトの名無しさんNGNG
ハードディスクの性能をフルにいかすには、ファイルシステムなんて(ry
0840デフォルトの名無しさんNGNG
移植性とか規格を隠れ蓑にしてる厚顔無知は確実に実在する
決して「切り込み隊長」的な仕事をしない
0841デフォルトの名無しさんNGNG
公然オナニー迷惑な「切り込み隊長」も確実に実在する
0842デフォルトの名無しさんNGNG
>>837
移植性を追及すべきか、アーキテクチャへの最適化をついきゅうすべきかを合理的に判断してこそプロ
0843デフォルトの名無しさんNGNG
追求を「ついきゅう」なんて書いちゃう俺はアマ
0844デフォルトの名無しさんNGNG
>>842
両立してこそプロ(の技量)
0845デフォルトの名無しさんNGNG
移植性は追求しろと
0846デフォルトの名無しさんNGNG
いやもうマ板の話の流れっつーか
0847デフォルトの名無しさんNGNG
>>841
無能ですね
0848デフォルトの名無しさんNGNG
何のかんの理屈つけては逃げ回るだけの敵前逃亡の専門家イラネ
0849デフォルトの名無しさんNGNG
なんのかんの理屈つけて、カプセル化、抽象化から逃げる池沼もイラネ

お前が出来ないからって、他の人も出来ないと思うな
0850デフォルトの名無しさんNGNG
なぜ荒れる(w
0851デフォルトの名無しさんNGNG
ホイポイカプセル化しとけ
0852デフォルトの名無しさんNGNG
夏休みが終わりに近づいてるから
0853デフォルトの名無しさんNGNG
>>849は、手段と目的を履き違える典型的な「切り込み隊長」(w
0854デフォルトの名無しさんNGNG
stringクラスには大文字を小文字に変換するメソッドとか
その逆のメソッドはありませんか?
MFC CStringのMakeUpper()やMakeLower()みたいな感じの。
0855デフォルトの名無しさんNGNG
ctype::tolower
■ このスレッドは過去ログ倉庫に格納されています