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

C++相談室 part34

レス数が950を超えています。1000を超えると書き込みができなくなります。
0001v(^・^)vNGNG
C++に関する質問やら話題やらはこちらへどうぞ。
ただし質問の前にはFAQに一通り目を通してください。
テンプレートライブラリ(STL含む)に関する質問は
専用の別スレにお願いッス。

過去スレ、関連スレ、関連リンクなどは >>2-20 あたり
0855デフォルトの名無しさんNGNG
ctype::tolower
0856デフォルトの名無しさんNGNG
std::transform(s.begin(),s.end(),s.begin(),static_cast<int(*)(int)>(std::tolower));

locale対応バージョンがうまく書けない。
0857デフォルトの名無しさんNGNG
面倒でつね… なんでメンバに実装されてないのかな…
0858デフォルトの名無しさんNGNG
>>857
派生クラス作っときゃええやん
使えるクラスができたら売るとか・・・
0859デフォルトの名無しさんNGNG
>>857
そりゃ、localeのせいだろ。
0860デフォルトの名無しさんNGNG
デストラクタで純粋仮想関数を呼び出したいのですがうまくいきません。
純粋仮想関数の中身を実装しないとコンパイル時に関数がないと言われるのですがなんででしょう?
↓ソースはこんな感じです。

#include <time.h>
#include <iostream>
class DyingMessage{
  virtual void say1() = 0;
  virtual void say2() = 0;
protected:
  ~DyingMessage(){
    ( time(NULL) %2 ) ? say1() : say2();
  }
};
class JiipanKeiji : public DyingMessage {
  void say1(){ std::cout << "なんじゃこりゃー"; }
  void say2(){ std::cout << "おらぁ死にたくないよ、死にたくない、死にたくないよ・"; }
};
class RAOU : public DyingMessage {
  void say1(){ std::cout << "我が生が(略"; }
  void say2(){ std::cout << "我が生涯に一片の悔いなし!ウオァァァアア!"; }
};
int main(void){
  JiipanKeiji jk;
  RAOU r;
}
0861デフォルトの名無しさんNGNG
>>860
~DyingMessage() が実行されるときには、ジーパンもラオウも既に死んでいる。
0862デフォルトの名無しさんNGNG
>860
コンストラクタとデストラクタ内では、仮想関数が仮想になれない。
デストラクタを仮想にしてそこに書くしか。
0863デフォルトの名無しさんNGNG
柴田望洋さんの、CプログラマのためのC++入門を買おうと思っているのですが
内容的に古いらしいのですが、大丈夫なのでしょうか?
0864デフォルトの名無しさんNGNG
>>861
まじで
台詞はいてからじゃないと名シーンが台無しに・・・。

>>862
すみません、virtual抜けてましたね。
でもデストラクタにvirtualつけてもやはりコンパイル通らないっす
って仰っているのはデストラクタにvirtualつけろってことではない?

それで実験としてDyingMessageのsay1とsay2を
cout << "犯人はヤス"; と定義してみたらと、
ジーパンもラオウも「犯人はヤス」しか言わなくなりました。
な、なにゆえ?
0865デフォルトの名無しさんNGNG
>>864
処理の順番はこうなる。
 DyingMessage()→RAOU()→ラオウの生涯→~RAOU()→~DyingMessage()
~RAOU()のタイミングでラオウは天に還ってしまう。
0866デフォルトの名無しさんNGNG
コンストラクタとデストラクタの中では、
関数呼び出しは(virtualであっても)「そのクラス」として行われるよ。
DyingMessageクラスではsay1, say2の中身は存在しないから、
コンパイラのメッセージは正しい。
実行時にヌルポ(pure virtual function call)を出す実装もある。

細かい話をすると、デストラクタやコンストラクタが親クラス→子クラス
と渡るときに、vtblのポインタが書き換わる。

これ、Javaと逆だから、多言語を渡り歩く人は要注意ッス。
Java方式もまたそれで問題あるんだけどね・・・
0867860NGNG
>>865
中身(インスタンス)はRAOUだから、say1、2はラオウのものを呼んでくれてもいいのに( ´Д⊂ヽ

>>866
>細かい話をすると、デストラクタやコンストラクタが親クラス→子クラス
>と渡るときに、vtblのポインタが書き換わる。
まじですか。vtblのポインタが書き換わるんですか。
main関数内と ~DyingMessageでのジーパン、ラオウのインスタンスのメモリアドレスが一緒だったんで、
ジーパンとラオウのvtblのsay1、say2が呼び出されてうまくいくかと思ってたのですが納得です。


結局のところ、どうしよう。
~DyingMessage上でラオウのsay1が実行させたいのですが。なんか考えます。
ありがとうございました。
0868デフォルトの名無しさんNGNG
>>867
> ~DyingMessage上でラオウのsay1が実行させたい
そうはいってもそのときにはもうラオウは居ないから、
ラオウに追加したメンバは触れないぞ。

生きているうちに遺言を作っておいて DyingMessage に保持させるといいかもしれない。
0869デフォルトの名無しさんNGNG
>>867
~DyingMessageが実行される時には
「お前(ラオウ)はもう死んでいる」から
ラオウのメンバを無理矢理呼び出すのもダメだよ。
0870860NGNG
>>868
できれば、>>860のラオウやジーパンクラスのソースのようにsay1、say2のみを定義するだけで他は何も手を加えず、
後は親クラスのDyingMessageがsay1、say2を使って処理してくれるようなのが理想なんです。
できるだけ子クラスは記述しなければならないソースを減らしたいんです。
でも、確かにラオウは破棄されてしまうわけだから今回の場合は無理っぽいですね。

>生きているうちに遺言を作っておいて DyingMessage に保持させるといいかもしれない。
それはいいアイデアかもしれないっす。ありがとうございます。
0871デフォルトの名無しさんNGNG
C++のデストラクタは、リソース開放のためだけに使うと思ったほうがええよ。
0872デフォルトの名無しさんNGNG
>>858
std::stringの派生クラスを作る奴は糞。
0873デフォルトの名無しさんNGNG
class x : public std::string
{
public: ~x() { std::cout << "x::dtor" << std::endl; }
};

main()
{
std::string* p=new x();
delete p;
}


実行結果
x::dtor

問題なし。
0874デフォルトの名無しさんNGNG
>>873
環境は?
0875デフォルトの名無しさんNGNG
>>874
お前が気にするのはそこなのか?
この場合問題なのはデフォルトコンストラクタしか使えんことだろ。
0876デフォルトの名無しさんNGNG
>>875
実行結果
0877デフォルトの名無しさんNGNG
>>876
Oh! Me としたことが釣られてしまいましたNeー!
0878デフォルトの名無しさんNGNG
VC++6で.cppと.defファイルをDLLにコンパイルする方法を教えて下さい
0879デフォルトの名無しさんNGNG
VCのスレ行ってください
0880デフォルトの名無しさんNGNG
>>872
> std::stringの派生クラスを作る奴は糞。
まぁ、作るなとは言わんが、この場合は

tolower(std::string&);
toupper(std::string&);

っつーフリー関数にしておいた方が、何かと幸せになれる気がする。
0881デフォルトの名無しさんNGNG
boost/algorithm/string/case_conv.hpp
0882デフォルトの名無しさんNGNG
std::ifstreamで
std::ifstream fin("somefile");
char str[1];
fin.getline( str, 256 ); // この結果勝手に256に拡張されるっぽい
などとできてしまうのですけどこれって仕様ですか?
0883デフォルトの名無しさんNGNG
>>882
未定義動作です。
0884デフォルトの名無しさんNGNG
>>882
拡張をしないまま暴力的に 256 byte 書き込んできてしまうだけ
道路の拡幅工事を立ち退き交渉も予告もせずにおっぱじめるようなもの
何が起きるのかは、おそらくご想像のとおり・・・
0885882NGNG
一見ちゃんと動いてるようでもやっぱり危険なコードだったんですね。
今度から気をつけます。ありがとうございました。
0886デフォルトの名無しさんNGNG
>>872
uppercase_traits作るんでもいーけどさ、
stringとの混用を前提とする場合、他にどーしよーもねーだろ
0887デフォルトの名無しさんNGNG
>>886 >>880-881
0888デフォルトの名無しさんNGNG
>>886
そのuppercase_traitsって、何してくれるの?
0889デフォルトの名無しさんNGNG
>>886
>>880
でいいやん。
なんで継承したがる?

つうか良く考えろよ。今から分かりやすく説明するからな。

お前は機能XXXを追加したくなった。
機能追加は継承だという浅はかな考えからstringから派生することにした。

class MyString : public std::string{
public:
void XXX();

/* 他のメソッドは略 */
};

こうしちゃったらさぁ、機能XXXを使うには
必ずMyStringクラスを構築する必要が出来るよな

MyString mystr=std_string_variable;
mystr.XXX();

これってかなーりムダだよな。
0890デフォルトの名無しさんNGNG
>>889
ちっとも解りやすくないぞ。何が言いたいんだ?
アップキャスト後に追加メソッドを使うコンテキストでへ来ちまったら
ダウンキャストが必要になるのはどんな作りのクラスでも一緒やん。
継承を全面否定したいのなら、同意はしないが理解はできる。
0891デフォルトの名無しさんNGNG
>>890
馬鹿はスルーしろよ
0892デフォルトの名無しさんNGNG
STLのコンテナクラス(ここではstd::string)のデストラクタが
virtual じゃないんじゃね?

>>889はJava厨の釣りと見た。

0893デフォルトの名無しさんNGNG
いや、機能追加したいがためだけに実装継承するぐらいなら委譲で何とかしろってのがセオリーじゃないのか?
0894デフォルトの名無しさんNGNG
コンテナには委譲を使うのが基本だね
0895デフォルトの名無しさんNGNG
public std::string
↑
メソッド追加するだけなのにpublic継承してる所が釣り
0896デフォルトの名無しさんNGNG
>>893
機能追加つーたら継承そのものやんけ
なんで「異常」な手段に拘るんだよ
0897デフォルトの名無しさんNGNG
それでこそ2ちゃんねら
0898デフォルトの名無しさんNGNG
↓まだ釣られる気かよ
0899デフォルトの名無しさんNGNG
継承に警鐘
0900900ズサーーー!!!NGNG

   ∩___∩         |
   | ノ\     ヽ        |
  /  ●゛  ● |        |
  | ∪  ( _●_) ミ       j
 彡、   |∪|   |       >>899
/     ∩ノ ⊃  ヽ  
(  \ / _ノ |  |
.\ “  /__|  |
  \ /___ /
0901デフォルトの名無しさんNGNG
900!
0902デフォルトの名無しさんNGNG
以下何事も無かったかのように再開
0903889NGNG
あれ、叩かれてる。説明あかんかったか。

よし、じゃあXXXとか言わずにuppercaseで書いたるか。

struct MyString : public std::string{
void uppercase();
};

ほれ、出来た。これでMyStringの大文字化はラクショーさ。

ああだけど、std::stringを使ってる部分もあるんだった。
これも大文字化しないといけない。

継承で機能追加
MyString mystr=std_string_variable;
mystr.uppercase();
std_string_variable=mystr;

外部関数で機能追加
uppercase(std_string_variable);

これでどうやろう?

基本的に継承は仮想関数のオーバーライドのためか
protectedなメンバに触りたい時くらいにしか使うべきではない。
0904デフォルトの名無しさんNGNG
>>903ヘ(_ _ヘ)☆\( ̄なんでやねん!

>MyString mystr=std_string_variable;
おまえ追加機能つかうちゅーてる時に予めアップキャストしとくんかい
アフォ言いな、比べ方の条件がちゃうやないけ!
0905デフォルトの名無しさんNGNG
このアホさ加減
Java厨っぽいな
継承悪
コンポジットサイコーみたいな
思考停止したデザパタ厨
0906889NGNG
>>904
?

じゃあstd_string_variableを大文字化するにはあんたならどうするん?

てかさっきから気になってたんやけど、アップキャストなんてしとらへんよ

アップやないし、そもそもキャストでもない

>>905
オレのことじゃないよな。俺は外部関数使えいうとるし
0907889NGNG
ていうか、マジに大文字化機能を追加するには
std::stringを継承して、そのサブクラスにメンバ関数追加するのが一番だと思ってるんか?
0908デフォルトの名無しさんNGNG
>>906
ああ、確かにstd_string_variableの定義を隠したままだねw
0909デフォルトの名無しさんNGNG
>>907
同じことじゃん、所詮はthisの渡し方
色んな書き方ができる中で今回はどれって選ぶだけ
0910889NGNG
>>908
定義?
std::string std_string_variable;
これでいいのか?

>>909
いやいや同じじゃないよ。
継承メンバ関数追加バージョンのuppercaseはstd::stringに対しては使えないんだよ。

継承メンバ関数追加を他の2、3人の奴がやってみ

A君は大文字化を追加したUppercaseStringを作った
B君は最後の文字を取り除く機能を追加したChopStringを作った
C君はその文字列をurlエンコードする機能を追加したURLEncoderStringを作った

じゃあ、大文字化の機能と最後の文字を取り除く機能とurlエンコードする機能全部を使いたいとき
一体どれを使ったらいいんだい?

外部関数でその機能を作ればこんなアホな自体にならないと思うけど。
0911デフォルトの名無しさんNGNG
>>910
>これでいいのか?
ああ、それでいい。
派生クラスで protected にアクセスできなくなるのと
同根の仮定を勝手に持ち込もうとしていることが判ったからな

また3人て新たな仮定を追加するのかよ、いい加減にしろや

色んな書き方ができる中で今回は継承を選ばないって場合の例ばかり持ち出しては
継承そのものを否定しようとする態度はよくわかった
0912デフォルトの名無しさんNGNG
>>910
3人でよけりゃ仮想継承って手もあるなw
0913デフォルトの名無しさんNGNG
別に外部関数の方がよりよく実装できるというあんたの主張にケチなんかつけてない
だから880には噛み付いてない

さっきも言ったがあんた自分の態度に思い当たるフシあるんじゃないの?
0914889NGNG
>>911
>継承そのものを否定しようとする態度はよくわかった
あれ?継承そのものを否定なんてしてないけど?
というか、オレは継承しまくり人間だよ。
実装継承もよくするしね。template<class T> class A : public T とかもしまくり。

ただ今回のケース、(>>854ね
は継承してメンバ関数追加 (>>858ね
は愚の骨頂やん?
だからいってるんやけど?なんか気に障った?
ヘタな説明にイラついたんやとしたらあやまるわ。ゴメン。
0915デフォルトの名無しさんNGNG
洋書の著者にありがちな態度でもある罠
0916デフォルトの名無しさんNGNG
>は愚の骨頂やん?

あんたのキャラクタか
0917889NGNG
>>913
じゃあなんでオレに噛み付いたんだよ。
>さっきも言ったがあんた自分の態度に思い当たるフシあるんじゃないの?
聞いてないし、フシも無い。

>>916
はは、関西弁なんて知らんからな。酷く疲れたぜ。
0918デフォルトの名無しさんNGNG































0919デフォルトの名無しさんNGNG
>>890
890 が ToLowerCase, ToUpperCase を追加した MyStringUL を作った。
俺が EUC, SJIS の相互変換できる MyStringES を作った。

で、両方の機能が使いたくなったらどうする? 気がつくと似て非なる
互換性のない文字列型がたくさん出来てることになりかねんぞ。

ねじ・くぎのような「部品」として使うクラス、プログラミング言語 C++ で
言うところの具象クラスは、可能な限り安易な仕様を早期に固めて、
安易な拡張はしない方が良い。まして継承は最悪の選択肢の一つだ。
0920デフォルトの名無しさんNGNG
>>919
virtual で多重継承して、C++の繊細さを堪能するというのもアリだと思うぞ。
堪能ってのは、実質デバッグの堪能だけどな。
ま、無理ではない。
0921デフォルトの名無しさんNGNG
ま、普通、自分で作るなら、
iterator使ったgeneric function書く。> toupper
0922デフォルトの名無しさんNGNG
>>920
すでに MyStringUL 使って書かれてるコードが大量にあったら、MyStringES に
クロスキャストするの? それは死にそうだ。
0923デフォルトの名無しさんNGNG
汎用ライブラリじゃないなら、普通はそのプロジェクト内だけで使う。
890 が ToLowerCase, ToUpperCase を追加した MyString を作った。
俺が EUC, SJIS の相互変換できる機能を、 MyString に追加した。
となるわな。インフラグループとかが、普通にやってることだ。
0924デフォルトの名無しさんNGNG
std::string を継承する
フリー関数を作る

どちらかでしか実現できないことなら仕方ないが、どっちでも実現できて
一方にはかなり痛いデメリットがある場合には、選択肢は自ずと決まると
思うんだが。
0925デフォルトの名無しさんNGNG
>>923
機能追加はなんでもかんでも継承だ、という安直な考えを持った、
オブジェクト指向習い始めて3日目くらいの奴がそのグループに多いとやっちゃうわな。
だけどそんなフツウを、世の中のフツウと勘違いしたらダメだ。
0926デフォルトの名無しさんNGNG
>>924-925
とりあえずやってみたらって言うのをずいぶん調子に乗って拡大解釈してるな、おまえ
選択以前のことを言ってるところへあーしろこーしろと思考まで代行してくれなくていいんだよ
それとも最後まで代行をやり通す責任感があって言ってるのか?
人が自分で物事を考えるときに金切り声で騒ぎ立てるのがただうるせえんだよ
物作ってるより人に暴言吐いてる方が楽しい奴が何か憶えたのを使いたくてこっち来たのか?
0927デフォルトの名無しさんNGNG
>>926
何切れてんだお前?
責任とって欲しいならそもそも2chに来るなよ。
0928デフォルトの名無しさんNGNG
お前のプロジェクトには、カスタマイズされた文字列クラスもないのかよ。
文字列操作系のグローバル関数満載かよ。
どんなプロジェクトだよ(w)
0929デフォルトの名無しさんNGNG































0930デフォルトの名無しさんNGNG
現在激しい電波を受信しています。ご注意ください。
0931デフォルトの名無しさんNGNG































0932デフォルトの名無しさんNGNG
多重継承のメモリ解放で疑問があります

class A { ... };
class B { ... };
class C : public A, public B { ... };
A, B, C全て仮想デストラクタを持っている

C* pc = new C;
B* pb = pc;
delete pb;

デストラクタは正しく呼ばれるが、pbのアドレス(pc != pbは確認済み)でメモリが解放されておかしくなる
と思ったのですが、operator newとdeleteをオーバーライドしてトレースしてみたところ
operator deleteではpcのアドレスが来ました。
delete pb;ではpbが指すのがCのオブジェクトなのかBのオブジェクトなのか区別できないはずなのに
どうしてpcのアドレスが求めることができたのでしょうか?
0933デフォルトの名無しさんNGNG
>>929-931
反論できないと荒しかよ(ゲラ
0934デフォルトの名無しさんNGNG
>>932
Exceptional C++ 嫁
0935デフォルトの名無しさんNGNG
>>926
浅はかな考えを指摘されたからって逆切れするなよ

>>928
お前の糞プロジェクトを中心にものごとを考えるなよ。
0936デフォルトの名無しさんNGNG































0937デフォルトの名無しさんNGNG
>>935
浅はかかどうかをお前が決めてやらなくていいんだよ
自分の設計に同意を求めたくて余裕なくしてるのはお前だろ
0938デフォルトの名無しさんNGNG































0939デフォルトの名無しさんNGNG
>>932
MSVCの例だが。
ttp://www.microsoft.com/japan/msdn/vs_previous/visualc/techmat/feature/jangrayhood/
0940デフォルトの名無しさんNGNG
>>937
明らかに継承の方が劣ってたじゃん。

>自分の設計に同意を求めたくて余裕なくしてるのはお前だろ
この一文がどっから出てきたのかわからないけど、そっくりそのままお返しします。ノシ
0941デフォルトの名無しさんNGNG































0942デフォルトの名無しさんNGNG
>>940
>この一文がどっから出てきたのかわからないけど

じゃ、何を必死になってるんだよ
0943デフォルトの名無しさんNGNG
>>942
必死なのはお前だw

なんだよ >>926は

文面が必死すぎ、余裕無さ過ぎ
0944デフォルトの名無しさんNGNG
>>942
必死になっているのはあなた一人に見えます。
あなたが「必死だな」と判断したのはどのレスですか?
レス番で教えてください。できれば理由も添えてください。
0945デフォルトの名無しさんNGNG
さっきからageてる人が、口調からしても必死に見える。
0946デフォルトの名無しさんNGNG
どっちも必死だよ、外でやっとくれ
0947デフォルトの名無しさんNGNG
かぶりまくったw自演認定されそう
0948デフォルトの名無しさんNGNG
継承の美しさを追求するあまり、
工数が増えたりするのはアフォらしいってのは、
みんな賛成してくれるだろ?な?駄目?
0949デフォルトの名無しさんNGNG































0950デフォルトの名無しさんNGNG
>>944
>>944
(・∀・)ジサクジエーン
0951デフォルトの名無しさんNGNG
継承って美しいか?
むしろ泥臭い。
最適解なら泥臭くても使う。
それは継承でもグローバル関数でも変わらない。
0952デフォルトの名無しさんNGNG
>>928
STL はコンテナ系も便利だが <algorithm> も便利だよ。
0953デフォルトの名無しさんNGNG
うわーい。こんな雰囲気なら漏れさんでも飛び込み参加できそうな予感。

class MyConstants
{
static const std::string TEST_TEST1;
static const std::string TEST_TEST2;
static const std::string TEST_TEST3;
}

こういうクラスから継承するときはどうするのが普通なの?
private virtualあたり?

class MyTest : public MyTestAbstract, private virtual MyConstants
{
}

教えてね♪
0954デフォルトの名無しさんNGNG
>>953
ポリシークラスでググる。
レス数が950を超えています。1000を超えると書き込みができなくなります。