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

C++相談室 part62

■ このスレッドは過去ログ倉庫に格納されています
0001デフォルトの名無しさん2008/05/27(火) 23:53:59
C++に関する質問やら話題やらはこちらへどうぞ。
ただし質問の前にはFAQに一通り目を通してください。
IDE (VC++など)などの使い方の質問はその開発環境のスレに
お願いします。

前スレ
C++相談室 part61
http://pc11.2ch.net/test/read.cgi/tech/1205059063/
0232デフォルトの名無しさん2008/06/13(金) 14:02:42
>>229
>227
0233デフォルトの名無しさん2008/06/13(金) 14:03:33
>>229
C++/CLIはC++を拡張した別の言語としてEcmaで標準化されてるよ。
0234デフォルトの名無しさん2008/06/13(金) 14:03:59
>>231
はい。但し、そのFunc()を例えばB.cppでは使いC.cppでは使わなかったとすると、一つだけになるかもしれません。
# 勿論、どちらでも使わない場合は一つもないかもしれないわけで。
0235デフォルトの名無しさん2008/06/13(金) 14:05:25
まぁそれをやるならせめて無名名前空間をつかってほしいところ
0236デフォルトの名無しさん2008/06/13(金) 14:13:59
>>234
うわぁぁ。そうなんだ。
staticつければ必ずひとつになると思っていました。ありがとう。
こういう場合ひとつだけにするにはテンプレートにするしかないのかな。
ヘッダに記述すること自体の是非は別として。
0237デフォルトの名無しさん2008/06/13(金) 14:19:46
>>236
いや、テンプレートにするかしないかとstaticかどうかは別の問題だから。
つーか、>231の場合でもどうせインライン展開されるから消えてなくなると思うし、
テンプレート関数にしたところでインライン展開されなければ複数できてもおかしくはない。

で、一つにしたい積極的な理由があるの?
0238デフォルトの名無しさん2008/06/13(金) 14:42:06
いろいろ言われそうだけどVCのプリコンパイル済みヘッダーの#include <stdafx.h>
が嫌だからなんです・・。
いろいろなコンパイラで使えればな〜と思っていたらどうしてもこれが邪魔で。
プリコンパイル済みヘッダーの設定変えればいいのでしょうけど、ファイルをコピー、
includeですぐに使えるような書き方はないかな〜と。
0239デフォルトの名無しさん2008/06/13(金) 14:50:41
あ、見当違いなこと書いてたかも。
上記理由でどうせ同じ関数なんだからひとつにしてファイルサイズ減らせないかなと
思っていた次第です。
0240デフォルトの名無しさん2008/06/13(金) 14:52:05
>>239
理由がそれだけなら、最適化するとどうせインライン展開されて消えてなくなるから気にするな。
0241デフォルトの名無しさん2008/06/13(金) 15:27:25
というか、あちこちに同じ中身が生成されるわけだから
ファイルサイズは逆に増えるよね。
0242デフォルトの名無しさん2008/06/13(金) 15:33:47
う〜ん、いろいろありがとう。
とりあえず最適化に任せてみます。
0243デフォルトの名無しさん2008/06/13(金) 16:11:17
===foo.h===
#include "bar.h"
class foo
{
(略)// barは出てこない
};

===foo.cxx===
#include "foo.h"
(略)// barが出てくる

とやるのと、
#include "bar.h"
をfoo.cxxの中に持ってくるのは、
どちらにどういうメリットデメリットがあるのでしょうか。
また、一般的にはどちらの書き方が推奨されますか。
0244デフォルトの名無しさん2008/06/13(金) 16:13:13
CLIって便利だよな
特に他言語で作ったクラスライブラリがそのまま使えるお得感は感動ものだ
0245デフォルトの名無しさん2008/06/13(金) 16:17:15
>>243
ヒント:依存関係、カプセル化
0246デフォルトの名無しさん2008/06/13(金) 17:46:14
>>243
後者。素直に使う所に書く、で必要十分。
前者にメリットは無い。fooを使うやつのコンパイルがbar.hの分遅くなるだけ。
0247デフォルトの名無しさん2008/06/13(金) 18:14:43
次のプログラムをエラー無くコンパイルしたいのですが、方法を教えてください。
//データの構造体-----------
struct dataA
{
int m_dataA;
CLSA * m_next //クラスのポインター
};
//使用するクラス------------
class CLSA
{
dataA m_dat[100];   //データの配列
};
dataAの中にクラスのポインターを持つ。この状態ではCLSAが無いと言われます。
順番を変えるとクラスの中でdataA構造体が無いと言われます。
対処方法が無いでしょうか?
0248デフォルトの名無しさん2008/06/13(金) 18:16:41
セミコロン抜けてた
CLSA * m_next; //クラスのポインター
0249デフォルトの名無しさん2008/06/13(金) 18:32:36
>>247
struct dataAの上に 「class CLSA;」を書く。

あと、どうでもいいけど何かよく分からないデータ構造だな。
dataA{ CLSA* m_parent; } とか
dataA{ dataA* m_next; } とか
CLSA{ CLSA* m_next; } なら分かるけど。
0250デフォルトの名無しさん2008/06/13(金) 20:00:26
出来ましたありがとうございます。基本的な内容ですねorz
データ構造は
root クラスインスタンス
|
|-ノード1クラスインスタンス
| : |-ノード1クラスインスタンス
| : |-ノード1クラスインスタンス
| :
|-ノード1クラスインスタンス

のような多段構造のようなもので、ノード分岐の意味をdataAの内部で示しています。
意味自体が単独で作られたり渡されたりするので、1つの構造体にしています。
0251デフォルトの名無しさん2008/06/13(金) 20:08:54
>>244
そのままシームレスに使えればだがな。

だが現実は・・・・ ハァー
0252デフォルトの名無しさん2008/06/13(金) 22:04:32
>>222
3.9.1 p1 は「バイト中のすべてのビットが値に反映される」とはいっても、ビット列と値が
1 対 1 でないこともあるんじゃないかな。
例えば char が符号付きで符号ビットと絶対値で表現する場合、値 0 を表現するビット列が
2 パターンある。その処理系で char* を通して値 0 を読み、その値を char* を通して書く
とビット列が変わる可能性があるんじゃないかな?
0253デフォルトの名無しさん2008/06/14(土) 00:03:39
char型のコピーはbit列をそのままコピーすると言っているのでは
0254デフォルトの名無しさん2008/06/14(土) 04:05:09
>>252
現行の規格で多少無理やり解釈すれば、 -0 と +0 は == で比較すれば
同じになるとしても、区別可能な(異なる value representation を持つ)二つの値
ということでコピーでビット列が変わる可能性は無い、とは言えそう。

ちょっと苦しいんで調べてみたところ、 C との互換性と合わせて見直しが
提案されているみたい。
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2631.html
この中で C99 の規格を基本的にはそのままパクりながら、 C99 では
保証が無いものの、 C++ で半ば慣習的に行われてきた char による
object representation のコピーを保証するため、以下のような記述の追加が
見られる。

The types unsigned char and char may be used for “bitwise” copy.
[Note: this means that if signed char has a negative zero which is
either a trapping value, or will be forced to positive zero on assignment,
plain char must be unsigned. ?end note]

てきとう訳:
型 unsigned char と char は「ビット的」コピーに使ってもよい。
[注: これは、もし signed char が負のゼロをトラップ値として持つか
代入において正のゼロに強制されるのであれば、ただの char は
unsigned でなければならない、ということを意味する。 -注ここまで]

提案とは別に、議論の中では C++ では2の補数を強制してしまうような話も
出ていたらしい。実際のところはそれでもいいのかもしれない。
0255デフォルトの名無しさん2008/06/14(土) 13:48:22
以下のような二種類の構造体のフィールドなのですが、
どちらがより適切なのでしょうか?

struct A
{
int length; // textの長さ
unsigned char text[0]; // 利用者側で好きに領域を確保して先頭を格納。
};

struct B
{
int length;
unsigned char text[1];
};

違いはtext[1]とtext[0]だけなのですが、
text[1]としてしまうと、

unsigned char text[] = "aiueo";
A* a = (A*)malloc(sizeof(A) + strlen(text));

としたときに(処理系依存ですが)
intで4バイト、unsigned charがパディングされて4バイト
さらに文字列の長さで5バイト確保されます。
これだとunsigned charがパディングされた4バイトは無駄な領域の気がします。

text[1]とするメリットはあるのでしょうか?
0256デフォルトの名無しさん2008/06/14(土) 14:12:25
>>255
宣言より大きい配列のアクセスはお勧めできないと思う。
環境依存なしでそういう構造を作りたいなら
struct A
{
int length; // textの長さ
};
A* a = (A*)malloc(sizeof(A) + strlen(text));
で確保して
char* buff=(char*)(a+1);
で文字列にアクセス


文字列の構造体を作りたいなら以下の方がお勧めかな
struct A
{
int length; // textの長さ
unsigned char* text;
};
0257デフォルトの名無しさん2008/06/14(土) 14:24:31
>>255
unsigned char text[0]; はC89では認められていない。
C99から導入されたflexible array memberを使うなら、
unsigned char text[];
0258デフォルトの名無しさん2008/06/14(土) 14:58:10
>>254
なるほど。
今回初めてC++の仕様書に目を通してみたけど未定義や処理系定義の部分が多くて
正確に解釈するのははなかなか難しいですね。
現状の処理系に合わせて処理系定義の部分を削っていけばかなりシンプルになると
思いますけど。
0259デフォルトの名無しさん2008/06/14(土) 15:18:36
>>258
処理系を前提とした入門書を読もう。 処理系未定義はその後で。
02602552008/06/14(土) 19:20:57
>>256さんどうもありがとうございます。

struct A{
int a;
unsigned char c[0];
};

gcc -c -pedantic test.c
としたら警告が出ました。

警告: ISO C forbids zero-size array 'b'

gccの独自拡張で可能になっているけれどC89自体では禁止されている
ということですね。
0261デフォルトの名無しさん2008/06/14(土) 20:30:10
おい、お前ら、googleでソースコードの検索ができることを知ってましたか?
http://www.google.co.jp/codesearch
0262デフォルトの名無しさん2008/06/14(土) 20:31:46
お前が今まで知らなかったことに驚愕。
0263デフォルトの名無しさん2008/06/14(土) 20:32:49
どういうときにつかうん
0264デフォルトの名無しさん2008/06/14(土) 20:34:41
codeをsearchする時
0265デフォルトの名無しさん2008/06/14(土) 20:54:24
>>261-264自演乙
0266デフォルトの名無しさん2008/06/14(土) 20:56:31
>>265
自演じゃねーよ、タコが
0267デフォルトの名無しさん2008/06/14(土) 20:58:47
>>266
イカですけど何か?
0268デフォルトの名無しさん2008/06/14(土) 20:59:26
>>267
創価、すまんかった
0269デフォルトの名無しさん2008/06/14(土) 23:11:26
# include<iostream>

using namespace std;
void func(int a = 0,long int b = 1000, double c = 2.9751)
{
cout<<"This is func[i].\n";
cout<<"a="<<a<<", b="<<b<<", c="<<c<<"\n\n";
}

void func(int a,double b =3.4152)
{
cout<<"This is func[ii].\n";
cout<<"a="<<a<<", b="<<b<<"\n\n";
}

void func(long int a)
{
cout<<"This is func[iii].\n";
cout<<"a="<<a<<"\n\n";
}


int main(void)
{
func(0,1000,2.9751);
func(0,3.14152);
func(0);
return 0;
}
オーバーロード関数が呼び出せませんと言うエラーが出るのですが、
何処が間違えているかわかりませんか?
未熟な私に教えていただけたらありがたいです。
0270デフォルトの名無しさん2008/06/14(土) 23:16:36
そんな
かわいそうな
つかいかたを
するな
0271デフォルトの名無しさん2008/06/14(土) 23:22:17
>>269
どれを呼んでいいのかワカンネ。とコンパイラ様は仰っておられる
0272デフォルトの名無しさん2008/06/14(土) 23:23:24
>>269
とりあえず、2個目と3個目のfuncを関数ごと
コメントアウトして実行してみ。
0273デフォルトの名無しさん2008/06/15(日) 02:27:52
もう引数全部意図する型にキャストしちゃえよ
0274デフォルトの名無しさん2008/06/15(日) 02:40:25
既定引数と多重定義は「まぜるな危険」だろ。
危険といっても、だいたいコンパイルエラーか警告だけど。

必要なら既定引数を使わないで多重定義をがんばることもやる。
といってもこういうのはありにしているが。
void f(int x);
void f(double x);
void f(int x, int y, int z = 0);
//実引数1個なら多重定義の解決の候補に既定引数は関係しない。
//実引数2個ならデフォルト引数を使うがfの候補は1つに決まっているので良し。
0275デフォルトの名無しさん2008/06/15(日) 03:02:24
fcloseの定義はどこにあるのでしょうか?
glibc-2.7のソースの中には無いようなのですが…
0276デフォルトの名無しさん2008/06/15(日) 03:07:07
libio/stdio.h
02772752008/06/15(日) 03:16:44
>>276
ありがとうございます!
あった!なるほど#defineされてたわけですね。
#define fclose(fp) _IO_new_fclose(fp)

で、_IO_new_fcloseをたどっていくと
最終的に__closeという関数が呼ばれているようなのですが、
今度こそ定義がglibcにはありませんでした。
ここから先はどうやって追えばよいのやら…
0278デフォルトの名無しさん2008/06/15(日) 03:17:10
>>275
マクロになってるとかじゃないの?
02792752008/06/15(日) 03:22:33
すみません__closeありました。
sysdeps/march/hurd/close.c
にありました。

実は、fcloseするときにバッファをディスクに同期する
部分がどうなってるのかを追いたかったのですが、
__closeから先はどうやら単にクローズしているだけのようです。
追いなおします。
0280デフォルトの名無しさん2008/06/15(日) 03:25:42
>>277
それはシステムコールじゃないかね。
そうだと、カーネルのソースを見る必要がある。
02812772008/06/15(日) 13:41:18
>>280
ありがとうございます。
Linuxのソースを見てみました。

linux/include/asm-i386/unistd.h
の中に

#define __NR_close 6

というのがあって、

linux/arch/i386/kernel/syscall_tables.S
の中のテーブルの6番の位置は

sys_close

となっていたので、sys_closeで探すと

linux/fs/open.c
の中にあって、その中で呼んでいる
filp_close
の中でflushとかやっていました。

ただ、__closeから__NR_closeのつながりがわかりませんでした。
これをどこかで#defineされているものなのでしょうか。
0282デフォルトの名無しさん2008/06/15(日) 13:58:38
C++のスレで話すような話題か、っつーのは置いといて...
今時のOSだと、ユーザアプリがファイルをcloseした
からといって、いちいちディスクに同期は取らんと思うけど。

libcのfclose()は、fflush()を呼ぶなりして、少なくとも
ユーザアプリ(というかlibc)が握ってるデータがkernel側に渡るようにはする。
が、kernel側がダーティページをどう処理するかは、バッファキャッシュ管理の
問題になるんでは。

ぶっちゃけsyncとかがあるのはそのためでしょ。
0283デフォルトの名無しさん2008/06/15(日) 22:44:48
class A { A(); ~A(); A(const A&); void operator=(const A&); friend class X; };
class X { class Impl; Impl* impl_; };

ユーザから見て A オブジェクトの生成と消去を X からしかできないようにしたいけど
impl_ の中で A を何らかのコンテナで管理するとき、そのコンテナは A と friend で
はないので A のコンストラクタとデストラクタを呼び出せません。A の中に実装のため
のクラスを friend として並べたくないし、実装の変更のたびに変更したくありません。

何か簡単に解決する方法はあるでしょうか?
0284デフォルトの名無しさん2008/06/15(日) 23:10:00
>>283
class A を class X か class X::Impl の private メンバにする。
0285デフォルトの名無しさん2008/06/16(月) 00:39:28
>>284
もちろんユーザは A の public メンバにアクセスできることが前提です。
0286デフォルトの名無しさん2008/06/16(月) 00:57:47
>>285
A を抽象インターフェースにして実体を >284
0287デフォルトの名無しさん2008/06/16(月) 01:12:34
template hackerさん。ヘルプミー。

template < class _T >
class C
 {
  public:
   template < class _Ta >
   void X();
 };

template < class _T >
void F()
{
C< int > obj1;
obj1.X<int>();

C< _T > obj2;
obj2.X<_T>();
}
0288デフォルトの名無しさん2008/06/16(月) 01:13:57
めっちゃ途中で書き込んだ。さーせん。
その上のコードの、obj2.X<_T>();がコンパイルエラーで通りません。
何ででしょうか
代替案とかあるでしょうか
0289デフォルトの名無しさん2008/06/16(月) 01:21:27
環境とエラーメッセージくらい書こうぜ
0290デフォルトの名無しさん2008/06/16(月) 01:29:17
ったりめーだろ
class _Tの実体がない
0291デフォルトの名無しさん2008/06/16(月) 01:29:37
じゃなかったclass _Tの定義がない
0292デフォルトの名無しさん2008/06/16(月) 01:33:42
>>286
ああ、その手があったね。

しかも A の唯一の派生クラスを A の friend にしておけば抽象である必要もないし
X の中に入れる必要もないね。

ありがとう。
0293デフォルトの名無しさん2008/06/16(月) 01:34:00
>>290
_Tはテンプレート引数だろ。
0294デフォルトの名無しさん2008/06/16(月) 01:57:05
>>288
obj2.template X<_T>();
その名がテンプレートであることを示せ

>>289
この場合はいらんかも
0295デフォルトの名無しさん2008/06/16(月) 02:02:54
>>294
>>287-288
0296デフォルトの名無しさん2008/06/16(月) 02:21:21
>>287 予約識別子死ね。
0297デフォルトの名無しさん2008/06/16(月) 02:25:06
>>292
> しかも A の唯一の派生クラスを A の friend にしておけば抽象である必要もないし
> X の中に入れる必要もないね。

何か変だな。一般的には、抽象でいいものに実装を混ぜる必要もないし、
スコープを無駄に広める必要もない、となりそうなもんなんだが。

まぁ望むものは得られたみたいなんで、書き込みに出てない部分の都合があっての
話ならどうでもいいけど。
0298デフォルトの名無しさん2008/06/16(月) 07:38:23
これでいいんだよね?

class A {
public:
 virtual ~A() { }
 virtual void Foo() = 0;
};

class X {
public:
 X();
 A* NewA();
private:
 class Impl* impl_;
};

class X::Impl {
public:
 A* NewA() {
  return new AImpl;
 }

private:
 class AImpl : public A {
 public:
  virtual void Foo();
 };
};

X::X() : impl_(new Impl) { }
A* X::NewA() { return impl_->NewA(); }
0299デフォルトの名無しさん2008/06/16(月) 12:39:10
>>297
抽象にしたくないのは単に性能のため。
Aは単純なクラスを想定しているのでそれほど実装を隠す必要はないから。
もしAの実装を隠したい場合はImpl方式にするかもしれない。
抽象クラスより優れている根拠は特にないが。

確かにAの派生はXに入れたほうが名前空間の汚染を軽減できるね。

>>298
デストラクタは private にしてユーザが削除できないようにしたい。
さらに特定のクラスにしか派生できないようにしほうが何となく安心。
0300デフォルトの名無しさん2008/06/16(月) 12:47:35
obj2.template X<_T>();

いや本当は知らないんですけどね
0301デフォルトの名無しさん2008/06/16(月) 23:02:51
>>294
>>300
thx。たすかりますた。thx。
>>287
解った。死ぬから_Tを使わせてくれ。
0302デフォルトの名無しさん2008/06/16(月) 23:03:51
> _T
処理系の予約語じゃねえか・・・
0303デフォルトの名無しさん2008/06/17(火) 21:38:29
ワラタ
0304デフォルトの名無しさん2008/06/17(火) 23:47:32
class x について ++x と x++ を定義する場合
operator++ はどうなるのかしらぁぁぁぁぁぁぁぁ
0305デフォルトの名無しさん2008/06/17(火) 23:53:14
++x → operator++()
x++ → operator++(int)

後者の引数はオーバーロードのためのダミー引数で、
それ以外の何かに使う物ではない。
0306デフォルトの名無しさん2008/06/17(火) 23:55:50
X & X::operator ++ (void) ;
X X::operator ++ (int) ;
03073042008/06/17(火) 23:59:07
ありがとうございました。orz
0308デフォルトの名無しさん2008/06/18(水) 07:40:42
関係無い話だけど、
テンプレート引数型で後置インクリメント使う馬鹿は氏ねと言いたい。
0309デフォルトの名無しさん2008/06/18(水) 07:56:32
いやむしろ型特性を利用して組み込み型のときだけ後置インクリメントにするという手も
0310デフォルトの名無しさん2008/06/18(水) 13:14:00
VC++ の2005を使用し、C++/CLIでアプリを作成しています。

ListViewに複数項目が登録されている場合、最下段での下キー押下で最上段へ、
また、最上段での上キー押下で最下段にフォーカスを移したいと思っています。

これをやるだけならキーイベントを拾って
「最下段で下キーが押された場合、フォーカス位置を0にする」
というようにすればいいのかと思ったのですが、ListViewのデフォルト機能(?)で
上下キー押下はフォーカス位置を1つずらすようになっています。

つまり、

1
2
3←フォーカス

この状態で下キーを押すと、フォーカス位置が0に戻る処理が実行された後、
フォーカス位置が1つ下にずれてしまうので

1
2←フォーカス
3

となってしまいました。

ListViewが持っているデフォルトのキーイベントを破棄できればいいのかと思ったのですが、
その捨て方も分かりませんでした・・・。

上記要件を満たす方法などがありますでしょうか?
0311デフォルトの名無しさん2008/06/18(水) 13:39:20
スレ違い
.NETスレ行け
0312デフォルトの名無しさん2008/06/18(水) 13:39:59
>>310
C++/CLIはC++を元にした別の独立した言語です。
なので基本的にはC++/CLIスレで質問して下さい。

しかし、言語自体でなく、
ListView(.NETコンポーネント)のことなので、
.NET総合スレか、人の多い(+構文が近い)C#スレをお勧めします。

System.Windows.Forms.ListView などは
C++/CLI, C#, VB.NETで同一のものです。
0313デフォルトの名無しさん2008/06/18(水) 13:52:12
次スレのテンプレには、
C++/CLI関連の誘導を加えた方がよさそうだな
0314デフォルトの名無しさん2008/06/18(水) 14:25:33
>>311、312
失礼しました
他スレにて再質問します
ありがとうございました
0315デフォルトの名無しさん2008/06/19(木) 14:53:55
以下のプログラムで、ddd() の中のようなキャストを行ってから bbb() の中で B::f() を正しく
呼び出せるでしょうか?

struct B { void f(); };
struct D : B {};
void bbb( B* b[], int size ) { for ( int i = 0; i < size; ++i ) b[i]->f(); }
void ddd( D* d[], int size ) { bbb( static_cast<B**>( static_cast<void*>( d ) ), size ); }
0316デフォルトの名無しさん2008/06/19(木) 15:46:32
ちょっと聞いてください。
enumハックを使ってクラスの中でSIZE_MAXという名前の定数を定義したんですよ。
そしたら、「error C2143: 構文エラー : '}' が '定数' の前にありません。」などのエラーが何個か出ました。
いろいろコメントアウトして原因を探ったら、vectorやstringなどをインクルードするとエラーが出る事がわかったんです。
で、インクルードファイルが壊れてると思い、再インストールしたんですが直らず、
結局、limits.hでSIZE_MAXという名前のマクロが定義されていたのが原因でした。
エラーメッセージに名前は出ないし、ネームスペースも無視される。
マクロって最低じゃないですか?
0317デフォルトの名無しさん2008/06/19(木) 16:00:25
マクロのない言語に乗り換えるといいと思うよ
0318デフォルトの名無しさん2008/06/19(木) 20:39:42
>>316
だからマクロは大文字を使うんだよ。
0319デフォルトの名無しさん2008/06/19(木) 21:15:33
やってみて結果を述べるのが自立した大人の行動と思う。
0320デフォルトの名無しさん2008/06/19(木) 21:15:56
319はto315
0321デフォルトの名無しさん2008/06/19(木) 21:21:24
だから、大文字の識別名はマクロ名以外には使わないという
お約束があるんだよ。
0322デフォルトの名無しさん2008/06/19(木) 21:46:10
>>319
すみません。特定の環境ということではなく一般的にできるかどうかです。
VC8で試したら動きます。
0323デフォルトの名無しさん2008/06/19(木) 22:37:03
やってみた結果から刷り込まれた処理系依存な「知識」が豊富な「大人」は痛いよな
0324デフォルトの名無しさん2008/06/19(木) 22:44:01
>>318,321
列挙型や定数に大文字使ってるのよく見かけるけどそんなお約束あるの?
0325デフォルトの名無しさん2008/06/19(木) 22:51:45
>>324
定数もマクロだったりするし、列挙型はスコープ無いから定数の代わりに使ったりするから
0326デフォルトの名無しさん2008/06/19(木) 23:29:25
std::wstring以外で、汎用的な文字列クラスって言うと何になるんでしょうか。
今までずっとATL::CStringWでやっていたのですが、std::wstringはいまいち不便で。
boostあたりになっちゃうんでしょうかね。
0327デフォルトの名無しさん2008/06/19(木) 23:49:29
>>325
>定数もマクロだったりするし、
定数をマクロで書くのはよくないんじゃない?
Effective C++ 1項に書いてあるように、これこそお約束なのでは。

>列挙型はスコープ無いから定数の代わりに使ったりするから
>>316の例だって列挙型を定数がわりに使ってハマってるように見えるんだが、何か違う?
0328デフォルトの名無しさん2008/06/20(金) 00:13:55
怪しかったらundef
CreateWindowとか
0329デフォルトの名無しさん2008/06/20(金) 00:35:20
質問です。
あるクラスのインナークラスを他のファイルで前方宣言したいと思っているのですが
どのように宣言すればよいのでしょうか…。

以下例です。
名前空間SpaceAに定義されたクラスClassAがあったとして
ClassA内部にはInnerClassAが定義されているとします。

namespace SpaceA {
class ClassA {
public:
class InnerClassA{}
}
}

このInnerClassAを他のファイルClassB.hで前方宣言して使うことはできるのでしょうか…。

// 前方宣言
namespace SpaceA {
class ClassA;
//struct ClassA::InnerClassA; // ClassAは名前空間じゃないからエラー…どう書けばいいのか
}
using SpaceA::ClassA;

namespace SpaceB {
class ClassB {
public:
ClassB( InnerClassA* p ); // イメージ的にはこんな感じで使いたい
}
}

よろしくお願いします。
0330デフォルトの名無しさん2008/06/20(金) 01:44:36
>>315
D* を B* としてアクセスするのは、規格の 3.10 p15 にあるエイリアスの制約に
違反するので、未定義動作。

ddd() の引数に B* の配列を似たようなキャストしてねじ込んだ場合は、上記の
制約を満たすことになるのでセーフ。
0331デフォルトの名無しさん2008/06/20(金) 01:48:50
>>329
無理。外側の ClassA の定義が必要。 ClassA の中で class InnerClassA; としてあれば
InnerClassA の定義は必要ない。
■ このスレッドは過去ログ倉庫に格納されています