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

【初心者歓迎】C/C++室 Ver.54【環境依存OK】

■ このスレッドは過去ログ倉庫に格納されています
0001デフォルトの名無しさん2008/05/14(水) 01:00:02
エスケープシーケンスやWin32APIなどの環境依存なものでもOK。
ただしその場合、質問者は必ず環境を書きましょう。
※sage禁止です(と代々スレに書いてありますが自己判断で)。
【前スレ】
【初心者歓迎】C/C++室 Ver.53【環境依存OK】
http://pc11.2ch.net/test/read.cgi/tech/1208989385/l50
【アップローダー】(質問が長い時はココ使うと便利)
http://kansai2channeler.hp.infoseek.co.jp/cgi-bin/joyful/joyful.htm
0071デフォルトの名無しさん2008/05/16(金) 03:09:58
>>69
>>70
なるほど、型が大きいほうに合わせられるっていうのは数値だけの計算にも当てはまるんですね。
変数だけしかそういう風にならないと勘違いしていました。
非常に分かりやすい説明ありがとうございました。勉強になりました。
0072デフォルトの名無しさん2008/05/16(金) 11:46:56
直書きの数値にも型はあるんだぞ
0073デフォルトの名無しさん2008/05/16(金) 11:58:44
リテラルと言いましょう
0074デフォルトの名無しさん2008/05/16(金) 13:09:38
すまん、用語には疎いもんで・・・
0075デフォルトの名無しさん2008/05/16(金) 20:39:22
>>20

>・templateクラスにして継承関係を逆にする
>  ※ template<class T> class base : T {};

これ、よく分からないので具体例あげてくれるとありがたい。
0076デフォルトの名無しさん2008/05/17(土) 03:21:50
struct A {
A() { f(); }
virtual void f() = 0;
};

struct B {
virtual void f(){}
};


を


template<class T>
struct X : T {
X() { f(); }
};

struct Y {
void f() {}
};

typedef X<Y> Z;
0077デフォルトの名無しさん2008/05/17(土) 03:22:49
修正
> X() { f(); }
X() { T::f(); }
0078デフォルトの名無しさん2008/05/17(土) 09:58:03
質問です
先日基底クラスのデストラクタを仮想にし忘れ、メモリーリークというお約束のミスをやってしまいました。
この手のミスを無くしたいのですが、warningを出させる方法や、チェックツールなどはないでしょうか?
環境はVS6.0です。

仮想関数テーブルへのアクセスによるオーバーヘッドは現状気にしていないので、全てのクラス関数を仮想にしたいのですが、たまにつけわすれてしまうのです。
0079デフォルトの名無しさん2008/05/17(土) 10:04:15
初心者です。
C++を学ぼうと思ってるんですが良い参考書orWebページはありますか?
0080752008/05/17(土) 10:09:49
>>76-77

ありがとう。
ただこの方法だと元々の継承関係が失われないかい?
(76はミスタイプと思うが、元々はstruct A : B)

質問者は継承関係は維持したいと思うけど。
0081752008/05/17(土) 10:13:13
>>80

というか継承と同じことをテンプレートで実現するってことかな。あってる?
0082デフォルトの名無しさん2008/05/17(土) 13:28:04
>>78
「メモリリーク 検出」とかでググれば解説してるサイトがいっぱいでてくる
0083デフォルトの名無しさん2008/05/17(土) 13:55:08
>>78
デストラクタを仮想にした基底クラスを作って、クラスを作るときに必ずそれを派生して使うようにすれば忘れることはない。
0084デフォルトの名無しさん2008/05/17(土) 13:57:15
>>83
それを忘れないようにするためって話じゃないのか?w
0085デフォルトの名無しさん2008/05/17(土) 13:58:33
>>83
デストラクタの話ね。
0086デフォルトの名無しさん2008/05/17(土) 14:43:18
>>83はルート基底クラス(C#とかのObject)を用意することで、
個別にvirtualを書かなくて済むようにした方が良い、って意味なのでは?

でもそしたら今度は、それ継承するのを忘れない方法は?
って話になりそうだけど。
0087デフォルトの名無しさん2008/05/17(土) 14:46:51
クラスを定義するときに専用のマクロを使うことにするとか
0088デフォルトの名無しさん2008/05/17(土) 14:57:06
>>87
それを忘れないようにするためって話じゃないのか?w
0089デフォルトの名無しさん2008/05/17(土) 15:02:42
>>88
忘れにくさという点で、
>>78より>83
それより>>87
と良くなっているように見えるけど。
0090デフォルトの名無しさん2008/05/17(土) 15:10:27
コピペ煽りに律儀に答えなくても
0091デフォルトの名無しさん2008/05/17(土) 15:42:28
class NewClass : public Object
の : public Objectを書かなかったらやっぱりバグるわけだしなー
それじゃ意味ないだろう

継承しなければコンパイルエラーになるようにできるなら、別だが。
0092デフォルトの名無しさん2008/05/17(土) 16:13:22
なんでループしてんの?
0093デフォルトの名無しさん2008/05/17(土) 16:19:14
struct Object{virtual ~Object(){};};
#define STD_STRUCT(NAME) struct NAME : public virtual Object
#define STD_CLASS(NAME) class NAME : public virtual Object

STD_CLASS(ClassA) {
public:
  ~ClassA(){std::cout << "~ClassA" << std::endl;}
};

STD_CLASS(ClassB), public ClassA {
public:
  ~ClassB(){std::cout << "~ClassB" << std::endl;}
};

void f()
{
  ClassA* p = new ClassB();
  delete p;
}
0094デフォルトの名無しさん2008/05/17(土) 16:27:10
そしてそのマクロを使うのをつい忘れるわけですね、わかります
0095デフォルトの名無しさん2008/05/17(土) 16:30:03
>>94

>>89

5レス前すら読めない人はこのスレに必要ありませんよ
0096デフォルトの名無しさん2008/05/17(土) 16:31:46
いや、お前ら質問者の意図無視しすぎだろw
0097デフォルトの名無しさん2008/05/17(土) 16:33:46
ツールでなんとかしたいと言ってる人間に、忘れないようにマクロを使いましょうってどんな返事なんだ
俺は必要としたことないから知らんが、書式チェックツールくらいないのか?
0098デフォルトの名無しさん2008/05/17(土) 16:36:19
virtual忘れをチェックしてくれるツールくらい自分作ればいいんじゃね
デストラクタは先頭に ~ が付いててわかりやすいから、
その前にvirtualが付いてるかどうかくらい簡単に判定できそう
そもそもデストラクタを書いてない場合は役に立たないが・・・
0099デフォルトの名無しさん2008/05/17(土) 16:38:42
>>96
>>78を読む限り、まずミスを無くしたい、という目的があって、
その方法として警告、チェックツール「など」、
と手段の例を挙げているので、
同じく、ミスを無くす/減らす方法を書いてるレスが
意図を無視してるようには見えないけど?
0100デフォルトの名無しさん2008/05/17(土) 17:06:19
とりあえず、抽象型へのアップキャストは極力控えて、
総称型プログラミングを覚えた方がいいと思った。
0101デフォルトの名無しさん2008/05/17(土) 17:08:30
>>100
実行時ポリモーフィズムが必要な場合はどうするの。
0102デフォルトの名無しさん2008/05/17(土) 17:10:55
だから極力控えて、って・・・。
0103デフォルトの名無しさん2008/05/17(土) 17:31:36
静的な方が安全というのは分かるが、
export のない C++ でジェネリックばっかやってると
コンパイルが重くて現実的じゃない事も。
0104デフォルトの名無しさん2008/05/17(土) 21:16:08
>>98
そしてそのツールでチェックするのをつい忘れるわけですね、わかります。
0105デフォルトの名無しさん2008/05/17(土) 22:34:11
>>104
make使うならMakefileに組み込めばおk。
総合環境なら・・・ カスタムビルドステップ?
0106デフォルトの名無しさん2008/05/17(土) 22:42:35
>>104
最悪、考え方としてはおかしくなったときにチェックすればいいわけだし。
0107デフォルトの名無しさん2008/05/17(土) 23:08:54
あれ?ちょっとずれるが
なんかの統合環境で、virtualな関数をオーバーライドする時にvirtualつけておかないとワーニング出すって設定できたよな?
これはvirtualですよー、わかってますかー?って意味合いで
0108デフォルトの名無しさん2008/05/18(日) 00:36:52
微妙に宣言間違えて、いつの間にか別の仮想関数が作られちゃうのを防ぐ方法ってないかな。
delphiならviryualで新しく作って、overrideでオーバーライドするから間違えたらエラーになるんだがなぁ
0109デフォルトの名無しさん2008/05/18(日) 00:37:37
virtualだな
0110デフォルトの名無しさん2008/05/18(日) 00:41:27
override は最近の言語によく取り入れられているね。
あれはいい仕様だと思う。
0111デフォルトの名無しさん2008/05/18(日) 01:18:54
>>107
それは余計なお世話な気もするな。コーディング規約レベルだと思う。
0112デフォルトの名無しさん2008/05/18(日) 01:25:16
いんや。
仮想関数じゃないつもりで関数追加して泣きを見るのを防止できる。
0113デフォルトの名無しさん2008/05/18(日) 09:07:18
なんにしろON/OFFできりゃいいんだよな
overrideはいい仕様だ
0114デフォルトの名無しさん2008/05/18(日) 11:38:49
Java みたいに問答無用で仮想関数にする言語は
typo で泣くことになる。
0115デフォルトの名無しさん2008/05/18(日) 11:52:39
そうした事もあって、C#では明示的にoverrideする必要になりましたとさ
0116デフォルトの名無しさん2008/05/18(日) 12:19:28
それにならって、javaもoverrideをチェックする
アノテーションが用意されました。
0117デフォルトの名無しさん2008/05/18(日) 13:19:39
そしてC++はほったらかしと。
0118デフォルトの名無しさん2008/05/18(日) 13:30:36
C++ は互換性を異常に気にするからな。
0119デフォルトの名無しさん2008/05/18(日) 13:40:20
override付きのときだけチェックしてくれれば良いんだけどなぁ。その他(virtual付き/何もなし)の時は今まで通りで。
0120デフォルトの名無しさん2008/05/18(日) 13:42:08
それはあんまり override の価値がない気が
0121デフォルトの名無しさん2008/05/18(日) 13:42:41
override が無い時に警告出してくれるならいいけど
0122デフォルトの名無しさん2008/05/19(月) 08:14:21
本に
Num = rand() % 100;
で、0から99までの範囲に含まれる値を取得できる
と書いてあるんですが、
どうやったらこうなるんですか?
0123デフォルトの名無しさん2008/05/19(月) 08:22:05
どうって見たまんまとしか答えようが…

rand() → ランダムな整数を取得
% 100 → 100で割った余り
0124デフォルトの名無しさん2008/05/19(月) 08:28:10
http://ja.wikipedia.org/wiki/Rand
とりあえずここらへん読んだ方がいいと思う
0125デフォルトの名無しさん2008/05/19(月) 09:43:37
■■■■■■■■■■■■■■■■
■                     ■  違う板にコピペすると、四角の枠の中に
■                     ■  メッセージとURLが現れる不思議な絵。
■                     ■
■       (´?ω?`)         ■  (その仕組みがリンク先に書いてある)
■                     ■
■                     ■  この原理を応用すると、まったく新しい
■                     ■  コピペが作れる予感。
■■■■■■■■■■■■■■■■
0126デフォルトの名無しさん2008/05/19(月) 10:10:45
てst

■■■■■■■■■■■■■■■■
■                     ■  違う板にコピペすると、四角の枠の中に
■                     ■  メッセージとURLが現れる不思議な絵。
■                     ■
■       (´・ω・`)         ■  (その仕組みがリンク先に書いてある)
■   http://kat.cc/19b06f     .■
■                     ■  この原理を応用すると、まったく新しい
■                     ■  コピペが作れる予感。
■■■■■■■■■■■■■■■■
0127デフォルトの名無しさん2008/05/19(月) 19:25:55
std::listのイテレータって、リストに追加や削除といった操作をしても
取得しなおさなくて使えますか?前にvectorで痛い目見たもんで・・・
0128デフォルトの名無しさん2008/05/19(月) 19:34:53
>>127
「erase 戻り値」でgoogle
0129デフォルトの名無しさん2008/05/19(月) 19:44:30
>>127
すまん勘違いした。
listでのinsertは全てのイテレータを無効にしない。
eraseは対象イテレータのみ無効になる。

つまり、大丈夫。
0130デフォルトの名無しさん2008/05/19(月) 20:13:43
>>129�dクス
0131デフォルトの名無しさん2008/05/19(月) 20:31:31
1クラスにつき1ヘッダ(全定義)+1ソース(全実体)
↑のやり方でやっていたのですが、どうも拙いと気付きました
巧いファイル構成を身に付けたいのですが、中々しっくり来る資料が…orz
コレ読んどけよって書籍やソースなどあればご指導願いします
0132デフォルトの名無しさん2008/05/19(月) 20:47:43

   A  L  L  h  p  p
01331312008/05/19(月) 22:32:00
すみませんでした。出直してきます
0134デフォルトの名無しさん2008/05/19(月) 23:42:52
質問です。VC++2008を使用しています。
以下のリソースファイルをプロジェクトに加えてコンパイルすると
Visual Studioが強制終了してしまいます。なぜでしょうか?

//--- menu.rc---
#include <windows.h>
#define MENU_NEW 2000
#define MENU_OPEN 2001

SAMPLE03 MENU DISCARDABLE
{
POPUP L"ファイル"
{
MENUITEM L"新規作成",MENU_NEW
MENUITEM L"読み込み",MENU_OPEN
}
}
0135デフォルトの名無しさん2008/05/19(月) 23:56:00
Lokiライブラリに小規模アロケートに特化したアロケータがあったと思うんですけど、Lokiのライブラリよりもメジャーなもので
同じニーズに応えたライブラリはありませんか?
0136デフォルトの名無しさん2008/05/20(火) 02:59:19
>>131
そのやりかたで何が拙いと思ったのか気になる。
0137デフォルトの名無しさん2008/05/20(火) 03:00:19
>>135
Loki のやつは知らないけど、たぶん segregated strage だろうってことで boost::pool でいいかな?
0138デフォルトの名無しさん2008/05/20(火) 11:45:17
とりあえずSTARTUPINFOにパイプを入れて子プロセスと繋ぐ事はできましたのですが、
すでに開いてるコマンドプロンプトの標準入出力を別のパイプに繋ぐことってできますか?
0139デフォルトの名無しさん2008/05/20(火) 12:20:20
>>122
でもそうやって乱数を取得しないほうがいいんだよ。
0140デフォルトの名無しさん2008/05/20(火) 18:17:41
C/C++ で、右シフト、左シフトを行う ">>" , "<<" はあるのですが、アセンブリで言うところの
ROL (ローテート) に相当する演算子は C/C++ では用意されてないのでしょうか?
0141デフォルトの名無しさん2008/05/20(火) 18:34:52
ありません。
0142デフォルトの名無しさん2008/05/20(火) 18:38:00
>>141
そうですか。どうもありがとうございました。
0143デフォルトの名無しさん2008/05/20(火) 18:45:38
_rotl
0144デフォルトの名無しさん2008/05/20(火) 19:28:50
>>143
なるほど、そんな関数があるんですね。教えてくださってどうもありがとうございました。
0145デフォルトの名無しさん2008/05/20(火) 19:37:27
童貞力に相当する演算子もないな。
0146デフォルトの名無しさん2008/05/20(火) 20:18:13
ひょっとして、 _rotl なんかの代わりに
int a; a=0x0000000f;
_asm{
MOV EBX,a
ROL EBX,2
MOV a,EBX
}
なんて書くのもアリだったりする?それとも、こういう実装の仕方は普通はしない?
0147デフォルトの名無しさん2008/05/20(火) 20:25:49
しないわ
ビット演算組み合わせるとか
0148デフォルトの名無しさん2008/05/20(火) 20:28:30
>>147
なるほど、分りました。お答えくださってどうもありがとうございました。
0149デフォルトの名無しさん2008/05/20(火) 20:39:02
gccなら
w = w<<s | w>>(32-s)
みたいにするとrotlにしてくれる場合がある。

確実にしたければ以下のようなインライン関数を作って呼び出せばOK

static inline uint32_t rotl(uint32_t src, uint8_t n) {
__asm__("roll %2,%1"
: "=r"(src)
: "0"(src), "cI"(n));
return src;
}

gccはインラインアセンブラも最適化の対象になるので、
単純に>>146みたいにするとおかしなことになるかも?
0150デフォルトの名無しさん2008/05/20(火) 21:10:48
確実にrolにならないといけないような場合はともかく、
それ以外の場合で環境依存を強めるのは止めようぜ・・・。
0151デフォルトの名無しさん2008/05/20(火) 22:54:25
質問です。
環境 VC6.0 / Windows2000
において、以下のコードで
i=m_NoList.begin()実行後に、
アクセスバイオレーションエラーが発生します。
デバッグでは、begin→STLのソース NEXT (_HEAD)・・・という箇所で
不正アドレスを参照しているように見えますが、原因が特定できません。
腑に落ちないのは、
if(m_NoList.size()>0)で要素があるにもかかわらず、
beginを実行するとエラーが発生するという点です。
使い方が間違っているのかもしれませんが、
ご見識のある方がいらしましたら、アドバイスお願いします m(__)m

Mutex.get(); ←ミューテックスでロックする
std::list<ListNo>::iterator i;
if(m_NoList.size()>0)
{
for ( i=m_NoList.begin(); i!=m_NoList.end();i++ ){ ←beginでエラー発生
if ( (*i) == No ) {
Mutex.release(); ←ミューテックスを開放する
return true;
}
}
Mutex.release(); ←ミューテックスを開放する
}
0152デフォルトの名無しさん2008/05/20(火) 23:00:40
Mutexとやらを外しても同じエラーなの?
ListNoの型は何?
0153デフォルトの名無しさん2008/05/21(水) 00:37:12
質問です。以下のプログラムの最終的な出力が7になるのがどうしても理解できません。
最初の*&x=,x=が2,2になるのはわかるんですが、2度目の*&x=が5になるのがわからなくて・・・
もし*&x=5なら最後の出力は10になる気がするのですが。

#include <stdio.h>

int x=1;

void f(int *p){
*p+=x;
}
int main(void){
int y;
f(&x);
printf("*&x=%d,x=%d\n",*&x,x);
{
int x=5;
printf("*&x=%d,x=%d\n",*&x,x);
f(&x);
y=x;
}
x=y;
printf("%d\n",x);
return 0;
}
0154デフォルトの名無しさん2008/05/21(水) 00:43:08
グローバル変数よりローカル変数の方が優先されるんだよ
でも二回目に表示されるxはスコープをy=xを終えた後
スコープを抜けて無効になるから結果が7になる
0155デフォルトの名無しさん2008/05/21(水) 00:44:02
日本語が…
>二回目に表示されるxはy=xを終えた後
の間違いでした
0156デフォルトの名無しさん2008/05/21(水) 00:44:51
>>153
*&xはいつもxと同じ、わざわざxと並べる意味はない。
外のxと中のxを別の変数だと思えば、理解しやすいと思う。

int グローバルなx=1;

void f(int *p) {
*p+=グローバルなx;
}
int main(void) {
  int y;
  f(&グローバルなx);
  printf("*&x=%d,x=%d\n",*&グローバルなx,グローバルなx);
  {
    int ローカルなx=5;
    printf("*&x=%d,x=%d\n",*&ローカルなx,ローカルなx);
    f(&ローカルなx);
    y=ローカルなx;
  }
  グローバルなx=y;
  printf("%d\n",グローバルなx);
  return 0;
}
0157デフォルトの名無しさん2008/05/21(水) 01:00:17
C++の継承について質問させてください。

class AAA
class BBB : public AAA
class CCC : public BBB
という継承しているクラスがあった時に、

AAA *pA;
BBB *pB;
CCC C, *pC;

pA = &C;
pB = &C;
pC = &C;

と書く事ができるのですが、
pA = &C;
pB = &C;
は、何でコンパイラに怒られないんでしょうか?
継承というのは、継承したクラスとしての扱いもできる、というような
イメージでいいんでしょうか?
0158デフォルトの名無しさん2008/05/21(水) 01:03:32
同じクラスから派生した物だったら大体似たようなもの筈だから
全部同じポインタ変数で扱えて便利なことも多い
01591532008/05/21(水) 01:07:19
>>154-156
解答ありがとうございました。
よく考えてみれば、int x=5;は代入ではなく変数の宣言でしたね…
ということは、最初のf(&x)でグローバルxにグローバルx+グローバルx(1+1=2)が代入されて、
次のf(&x)ではローカルxにローカルx+グローバルx(5+2=7)が代入され、
最後にローカルx→y→グローバルx(出力)という考え方でよいのでしょうか。
0160デフォルトの名無しさん2008/05/21(水) 01:11:22
そうそう
01611572008/05/21(水) 01:25:15
>>158さん
レスありがとうございます。

> 同じクラスから派生した物だったら大体似たようなもの筈だから
とありますが、構造体の場合は、
中身が全く一緒だとしてもコンパイルでエラーが出ますよね?

struct AA
struct BB

AA *p, A;
BB B;

p = &A;
p = &B; ←キャスト違い

p = (AA*)(&B)
上のようにキャストを変更してあげればコンパイルは通りますが、
継承したクラスの場合は、勝手にこのような処理をしてくれているのでしょうか?
何でクラスの継承の場合は問題なくコンパイルが通るのかが気になってしまって…。
0162デフォルトの名無しさん2008/05/21(水) 01:28:48
そうしてくれるようにしないと継承というシステムの本領が発揮できないから
つまりそうなるようにわざわざ作った
0163デフォルトの名無しさん2008/05/21(水) 01:29:09
派生クラスってのは基底クラスのオブジェクトでもあるってのが言語上の仕様だからな
0164デフォルトの名無しさん2008/05/21(水) 01:31:49
別々のモノを中身が全く一緒だと知ってるのは人間だけだもんなー
0165デフォルトの名無しさん2008/05/21(水) 01:36:44
Cの構造体的な発想では
基底クラス←派生クラス
っていうポインタの代入はダウンキャストだもんな。
そこがいまだにしっくり来ない。
01661572008/05/21(水) 01:46:32
皆様ありがとうございます。
継承したクラスとしての扱いもできるのは
とりあえずそういう仕様だという事なのですね。
おかげさまで勉強になりました。
ありがとうございました!
0167デフォルトの名無しさん2008/05/21(水) 02:16:00
#include <stdio.h>

int main(void){
int a[]={0,0,0,0};
int k=1;
a[k]=1;
a[a[k]]=2;
printf("%d\n",a[a[k]]);
return 0;
}

で、出力が2ではなく0になるのですがどうしてでしょうか。
ご教授のほどよろしくお願いします。
0168デフォルトの名無しさん2008/05/21(水) 02:30:40
#include <stdio.h>

int main(void){
int a[]={0,0,0,0};
int k=1;
a[k]=1;
a[a[k]]=2;        ←ここで a[a[k]]→a[a[1]]→a[1]=2になってる
printf("%d\n",a[a[k]]); ←つまりここでは a[a[k]]→a[a[1]]→a[2]なので0のまま
return 0;
}
0169デフォルトの名無しさん2008/05/21(水) 02:30:45
>>167
#include <stdio.h>

int main(void){
int a[]={0,0,0,0};
int k=1;
a[k]=1; // a[k] == a[1]
a[a[k]]=2; // a[a[k]] == a[a[1]] == a[1]
printf("%d\n",a[a[k]]); // a[a[k]] == a[a[1]] == a[2]
return 0;
}
0170デフォルトの名無しさん2008/05/21(水) 02:31:51
ついでにご教授じゃなくてご教示な
0171デフォルトの名無しさん2008/05/21(水) 02:35:31
そんな漢字の細かい事どうでもいいんじゃい ボケ
教えて感がでてればええんじゃい
■ このスレッドは過去ログ倉庫に格納されています