C++相談室 part62
■ このスレッドは過去ログ倉庫に格納されています
0001デフォルトの名無しさん
2008/05/27(火) 23:53:59ただし質問の前にはFAQに一通り目を通してください。
IDE (VC++など)などの使い方の質問はその開発環境のスレに
お願いします。
前スレ
C++相談室 part61
http://pc11.2ch.net/test/read.cgi/tech/1205059063/
0232デフォルトの名無しさん
2008/06/13(金) 14:02:42>227
0233デフォルトの名無しさん
2008/06/13(金) 14:03:33C++/CLIはC++を拡張した別の言語としてEcmaで標準化されてるよ。
0234デフォルトの名無しさん
2008/06/13(金) 14:03:59はい。但し、そのFunc()を例えばB.cppでは使いC.cppでは使わなかったとすると、一つだけになるかもしれません。
# 勿論、どちらでも使わない場合は一つもないかもしれないわけで。
0235デフォルトの名無しさん
2008/06/13(金) 14:05:250236デフォルトの名無しさん
2008/06/13(金) 14:13:59うわぁぁ。そうなんだ。
staticつければ必ずひとつになると思っていました。ありがとう。
こういう場合ひとつだけにするにはテンプレートにするしかないのかな。
ヘッダに記述すること自体の是非は別として。
0237デフォルトの名無しさん
2008/06/13(金) 14:19:46いや、テンプレートにするかしないかとstaticかどうかは別の問題だから。
つーか、>231の場合でもどうせインライン展開されるから消えてなくなると思うし、
テンプレート関数にしたところでインライン展開されなければ複数できてもおかしくはない。
で、一つにしたい積極的な理由があるの?
0238デフォルトの名無しさん
2008/06/13(金) 14:42:06が嫌だからなんです・・。
いろいろなコンパイラで使えればな〜と思っていたらどうしてもこれが邪魔で。
プリコンパイル済みヘッダーの設定変えればいいのでしょうけど、ファイルをコピー、
includeですぐに使えるような書き方はないかな〜と。
0239デフォルトの名無しさん
2008/06/13(金) 14:50:41上記理由でどうせ同じ関数なんだからひとつにしてファイルサイズ減らせないかなと
思っていた次第です。
0240デフォルトの名無しさん
2008/06/13(金) 14:52:05理由がそれだけなら、最適化するとどうせインライン展開されて消えてなくなるから気にするな。
0241デフォルトの名無しさん
2008/06/13(金) 15:27:25ファイルサイズは逆に増えるよね。
0242デフォルトの名無しさん
2008/06/13(金) 15:33:47とりあえず最適化に任せてみます。
0243デフォルトの名無しさん
2008/06/13(金) 16:11:17#include "bar.h"
class foo
{
(略)// barは出てこない
};
===foo.cxx===
#include "foo.h"
(略)// barが出てくる
とやるのと、
#include "bar.h"
をfoo.cxxの中に持ってくるのは、
どちらにどういうメリットデメリットがあるのでしょうか。
また、一般的にはどちらの書き方が推奨されますか。
0244デフォルトの名無しさん
2008/06/13(金) 16:13:13特に他言語で作ったクラスライブラリがそのまま使えるお得感は感動ものだ
0245デフォルトの名無しさん
2008/06/13(金) 16:17:15ヒント:依存関係、カプセル化
0246デフォルトの名無しさん
2008/06/13(金) 17:46:14後者。素直に使う所に書く、で必要十分。
前者にメリットは無い。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:41CLSA * m_next; //クラスのポインター
0249デフォルトの名無しさん
2008/06/13(金) 18:32:36struct dataAの上に 「class CLSA;」を書く。
あと、どうでもいいけど何かよく分からないデータ構造だな。
dataA{ CLSA* m_parent; } とか
dataA{ dataA* m_next; } とか
CLSA{ CLSA* m_next; } なら分かるけど。
0250デフォルトの名無しさん
2008/06/13(金) 20:00:26データ構造は
root クラスインスタンス
|
|-ノード1クラスインスタンス
| : |-ノード1クラスインスタンス
| : |-ノード1クラスインスタンス
| :
|-ノード1クラスインスタンス
のような多段構造のようなもので、ノード分岐の意味をdataAの内部で示しています。
意味自体が単独で作られたり渡されたりするので、1つの構造体にしています。
0251デフォルトの名無しさん
2008/06/13(金) 20:08:54そのままシームレスに使えればだがな。
だが現実は・・・・ ハァー
0252デフォルトの名無しさん
2008/06/13(金) 22:04:323.9.1 p1 は「バイト中のすべてのビットが値に反映される」とはいっても、ビット列と値が
1 対 1 でないこともあるんじゃないかな。
例えば char が符号付きで符号ビットと絶対値で表現する場合、値 0 を表現するビット列が
2 パターンある。その処理系で char* を通して値 0 を読み、その値を char* を通して書く
とビット列が変わる可能性があるんじゃないかな?
0253デフォルトの名無しさん
2008/06/14(土) 00:03:390254デフォルトの名無しさん
2008/06/14(土) 04:05:09現行の規格で多少無理やり解釈すれば、 -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宣言より大きい配列のアクセスはお勧めできないと思う。
環境依存なしでそういう構造を作りたいなら
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:31unsigned char text[0]; はC89では認められていない。
C99から導入されたflexible array memberを使うなら、
unsigned char text[];
0258デフォルトの名無しさん
2008/06/14(土) 14:58:10なるほど。
今回初めてC++の仕様書に目を通してみたけど未定義や処理系定義の部分が多くて
正確に解釈するのははなかなか難しいですね。
現状の処理系に合わせて処理系定義の部分を削っていけばかなりシンプルになると
思いますけど。
0259デフォルトの名無しさん
2008/06/14(土) 15:18:36処理系を前提とした入門書を読もう。 処理系未定義はその後で。
0260255
2008/06/14(土) 19:20:57struct 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:10http://www.google.co.jp/codesearch
0262デフォルトの名無しさん
2008/06/14(土) 20:31:460263デフォルトの名無しさん
2008/06/14(土) 20:32:490264デフォルトの名無しさん
2008/06/14(土) 20:34:410265デフォルトの名無しさん
2008/06/14(土) 20:54:240266デフォルトの名無しさん
2008/06/14(土) 20:56:31自演じゃねーよ、タコが
0267デフォルトの名無しさん
2008/06/14(土) 20:58:47イカですけど何か?
0268デフォルトの名無しさん
2008/06/14(土) 20:59:26創価、すまんかった
0269デフォルトの名無しさん
2008/06/14(土) 23:11:26using 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どれを呼んでいいのかワカンネ。とコンパイラ様は仰っておられる
0272デフォルトの名無しさん
2008/06/14(土) 23:23:24とりあえず、2個目と3個目のfuncを関数ごと
コメントアウトして実行してみ。
0273デフォルトの名無しさん
2008/06/15(日) 02:27:520274デフォルトの名無しさん
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:24glibc-2.7のソースの中には無いようなのですが…
0276デフォルトの名無しさん
2008/06/15(日) 03:07:070277275
2008/06/15(日) 03:16:44ありがとうございます!
あった!なるほど#defineされてたわけですね。
#define fclose(fp) _IO_new_fclose(fp)
で、_IO_new_fcloseをたどっていくと
最終的に__closeという関数が呼ばれているようなのですが、
今度こそ定義がglibcにはありませんでした。
ここから先はどうやって追えばよいのやら…
0278デフォルトの名無しさん
2008/06/15(日) 03:17:10マクロになってるとかじゃないの?
0279275
2008/06/15(日) 03:22:33sysdeps/march/hurd/close.c
にありました。
実は、fcloseするときにバッファをディスクに同期する
部分がどうなってるのかを追いたかったのですが、
__closeから先はどうやら単にクローズしているだけのようです。
追いなおします。
0280デフォルトの名無しさん
2008/06/15(日) 03:25:42それはシステムコールじゃないかね。
そうだと、カーネルのソースを見る必要がある。
0281277
2008/06/15(日) 13:41:18ありがとうございます。
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今時のOSだと、ユーザアプリがファイルをcloseした
からといって、いちいちディスクに同期は取らんと思うけど。
libcのfclose()は、fflush()を呼ぶなりして、少なくとも
ユーザアプリ(というかlibc)が握ってるデータがkernel側に渡るようにはする。
が、kernel側がダーティページをどう処理するかは、バッファキャッシュ管理の
問題になるんでは。
ぶっちゃけsyncとかがあるのはそのためでしょ。
0283デフォルトの名無しさん
2008/06/15(日) 22:44:48class X { class Impl; Impl* impl_; };
ユーザから見て A オブジェクトの生成と消去を X からしかできないようにしたいけど
impl_ の中で A を何らかのコンテナで管理するとき、そのコンテナは A と friend で
はないので A のコンストラクタとデストラクタを呼び出せません。A の中に実装のため
のクラスを friend として並べたくないし、実装の変更のたびに変更したくありません。
何か簡単に解決する方法はあるでしょうか?
0284デフォルトの名無しさん
2008/06/15(日) 23:10:00class A を class X か class X::Impl の private メンバにする。
0285デフォルトの名無しさん
2008/06/16(月) 00:39:28もちろんユーザは A の public メンバにアクセスできることが前提です。
0286デフォルトの名無しさん
2008/06/16(月) 00:57:47A を抽象インターフェースにして実体を >284
0287デフォルトの名無しさん
2008/06/16(月) 01:12:34template < 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:270290デフォルトの名無しさん
2008/06/16(月) 01:29:17class _Tの実体がない
0291デフォルトの名無しさん
2008/06/16(月) 01:29:370292デフォルトの名無しさん
2008/06/16(月) 01:33:42ああ、その手があったね。
しかも A の唯一の派生クラスを A の friend にしておけば抽象である必要もないし
X の中に入れる必要もないね。
ありがとう。
0293デフォルトの名無しさん
2008/06/16(月) 01:34:00_Tはテンプレート引数だろ。
0294デフォルトの名無しさん
2008/06/16(月) 01:57:05obj2.template X<_T>();
その名がテンプレートであることを示せ
>>289
この場合はいらんかも
0295デフォルトの名無しさん
2008/06/16(月) 02:02:54>>287-288
0296デフォルトの名無しさん
2008/06/16(月) 02:21:210297デフォルトの名無しさん
2008/06/16(月) 02:25:06> しかも A の唯一の派生クラスを A の friend にしておけば抽象である必要もないし
> X の中に入れる必要もないね。
何か変だな。一般的には、抽象でいいものに実装を混ぜる必要もないし、
スコープを無駄に広める必要もない、となりそうなもんなんだが。
まぁ望むものは得られたみたいなんで、書き込みに出てない部分の都合があっての
話ならどうでもいいけど。
0298デフォルトの名無しさん
2008/06/16(月) 07:38:23class 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抽象にしたくないのは単に性能のため。
Aは単純なクラスを想定しているのでそれほど実装を隠す必要はないから。
もしAの実装を隠したい場合はImpl方式にするかもしれない。
抽象クラスより優れている根拠は特にないが。
確かにAの派生はXに入れたほうが名前空間の汚染を軽減できるね。
>>298
デストラクタは private にしてユーザが削除できないようにしたい。
さらに特定のクラスにしか派生できないようにしほうが何となく安心。
0300デフォルトの名無しさん
2008/06/16(月) 12:47:35いや本当は知らないんですけどね
0301デフォルトの名無しさん
2008/06/16(月) 23:02:51>>300
thx。たすかりますた。thx。
>>287
解った。死ぬから_Tを使わせてくれ。
0302デフォルトの名無しさん
2008/06/16(月) 23:03:51処理系の予約語じゃねえか・・・
0303デフォルトの名無しさん
2008/06/17(火) 21:38:290304デフォルトの名無しさん
2008/06/17(火) 23:47:32operator++ はどうなるのかしらぁぁぁぁぁぁぁぁ
0305デフォルトの名無しさん
2008/06/17(火) 23:53:14x++ → operator++(int)
後者の引数はオーバーロードのためのダミー引数で、
それ以外の何かに使う物ではない。
0306デフォルトの名無しさん
2008/06/17(火) 23:55:50X X::operator ++ (int) ;
0307304
2008/06/17(火) 23:59:070308デフォルトの名無しさん
2008/06/18(水) 07:40:42テンプレート引数型で後置インクリメント使う馬鹿は氏ねと言いたい。
0309デフォルトの名無しさん
2008/06/18(水) 07:56:320310デフォルトの名無しさん
2008/06/18(水) 13:14:00ListViewに複数項目が登録されている場合、最下段での下キー押下で最上段へ、
また、最上段での上キー押下で最下段にフォーカスを移したいと思っています。
これをやるだけならキーイベントを拾って
「最下段で下キーが押された場合、フォーカス位置を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:59C++/CLIはC++を元にした別の独立した言語です。
なので基本的にはC++/CLIスレで質問して下さい。
しかし、言語自体でなく、
ListView(.NETコンポーネント)のことなので、
.NET総合スレか、人の多い(+構文が近い)C#スレをお勧めします。
System.Windows.Forms.ListView などは
C++/CLI, C#, VB.NETで同一のものです。
0313デフォルトの名無しさん
2008/06/18(水) 13:52:12C++/CLI関連の誘導を加えた方がよさそうだな
0314デフォルトの名無しさん
2008/06/18(水) 14:25:33失礼しました
他スレにて再質問します
ありがとうございました
0315デフォルトの名無しさん
2008/06/19(木) 14:53:55呼び出せるでしょうか?
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:32enumハックを使ってクラスの中でSIZE_MAXという名前の定数を定義したんですよ。
そしたら、「error C2143: 構文エラー : '}' が '定数' の前にありません。」などのエラーが何個か出ました。
いろいろコメントアウトして原因を探ったら、vectorやstringなどをインクルードするとエラーが出る事がわかったんです。
で、インクルードファイルが壊れてると思い、再インストールしたんですが直らず、
結局、limits.hでSIZE_MAXという名前のマクロが定義されていたのが原因でした。
エラーメッセージに名前は出ないし、ネームスペースも無視される。
マクロって最低じゃないですか?
0317デフォルトの名無しさん
2008/06/19(木) 16:00:250318デフォルトの名無しさん
2008/06/19(木) 20:39:42だからマクロは大文字を使うんだよ。
0319デフォルトの名無しさん
2008/06/19(木) 21:15:330320デフォルトの名無しさん
2008/06/19(木) 21:15:560321デフォルトの名無しさん
2008/06/19(木) 21:21:24お約束があるんだよ。
0322デフォルトの名無しさん
2008/06/19(木) 21:46:10すみません。特定の環境ということではなく一般的にできるかどうかです。
VC8で試したら動きます。
0323デフォルトの名無しさん
2008/06/19(木) 22:37:030324デフォルトの名無しさん
2008/06/19(木) 22:44:01列挙型や定数に大文字使ってるのよく見かけるけどそんなお約束あるの?
0325デフォルトの名無しさん
2008/06/19(木) 22:51:45定数もマクロだったりするし、列挙型はスコープ無いから定数の代わりに使ったりするから
0326デフォルトの名無しさん
2008/06/19(木) 23:29:25今までずっとATL::CStringWでやっていたのですが、std::wstringはいまいち不便で。
boostあたりになっちゃうんでしょうかね。
0327デフォルトの名無しさん
2008/06/19(木) 23:49:29>定数もマクロだったりするし、
定数をマクロで書くのはよくないんじゃない?
Effective C++ 1項に書いてあるように、これこそお約束なのでは。
>列挙型はスコープ無いから定数の代わりに使ったりするから
>>316の例だって列挙型を定数がわりに使ってハマってるように見えるんだが、何か違う?
0328デフォルトの名無しさん
2008/06/20(金) 00:13:55CreateWindowとか
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:36D* を B* としてアクセスするのは、規格の 3.10 p15 にあるエイリアスの制約に
違反するので、未定義動作。
ddd() の引数に B* の配列を似たようなキャストしてねじ込んだ場合は、上記の
制約を満たすことになるのでセーフ。
0331デフォルトの名無しさん
2008/06/20(金) 01:48:50無理。外側の ClassA の定義が必要。 ClassA の中で class InnerClassA; としてあれば
InnerClassA の定義は必要ない。
■ このスレッドは過去ログ倉庫に格納されています