C++相談室 part146
レス数が1000を超えています。これ以上書き込みはできません。
>>937
>デストラクタをvirtualにする必要があるのは、baseのポインタ経由でdeleteする場合だけ
mjk、 セオリーとして覚えてる人多いけど、何故なのかまで考えてない人が多い例の一つだね
要するにdeleteする基底のポインタからデストラクタを呼ぶ際に末端のデストラクタを呼ぶ方法(vtable)が必要というだけ
末端のデストラクタを呼べれば、そこから基底のデストラクタを呼んでいくのは何が基底かわかりきってるから自動で出来る >>941
>基底のポインタからデストラクタを呼ぶ際に末端のデストラクタを呼ぶ方法(vtable)が必要というだけ
mjk、 永遠の初心者です、お願いします
1. 式で if 文を表現したいときは条件演算子(三項演算子 ?: )が使えますが、同じく式でループ構造を表す方法は C++11 以後にありますでしょうか?
2. 1 の質問の理由としては、C++ は Java とちがって uper() がなく、派生クラスのコンストラクタの基底クラス初期化部分に式しか書けません、ここにループを書くとすれば「コンストラクタ用メンバ関数(メソッド)」を置いていますがいかにも無様だと思っています…
3. ある既存のクラスに皮をかぶせて機能アップを図るとき、もとのクラスの派生クラスとして機能アップ部分を既述することは、よくある定石でしょうか、それともあまりしないことでしょうか?
---
以上3点の質問は以下のプログラムを書いていて感じました
お題は「エラトステネスのふるい」、ただし、当初、まっとうにふるいを書いた後、機能アップ項目として
篩部分に格納する数は 2n + 1 奇数に限定する、あるいは 6n + 1, 6n + 5 の形のみに限定する
等を元の篩に対して派生クラスとして記述しました
https://ideone.com/YPlfsC >>943
ラムダ式の出番かな?
void test(bool flag) { flag ? []{ for(int i = 0; i < 10; ++i) cout << i; } : throw 1; } エラストテネス
6n+1, 6n+5だけ保持とかってみんな考えるよね
ちなみに
巨大なテーブル作成時のパフォーマンスを上げるなら
キャッシュが効くよう分割処理するのが非常に効果的
スレッド分割の為にいずれにしろ分割処理は作る事になる >>943
初期化部分に複雑な処理をベタ書きする方が無様だと思うよ。
初期化リストの中にそんなごちゃごちゃしたこと書きたい?
ワイが思うだけなので世間でどう思われてるかは知らんけどとりあえずひとつの意見として。 >>939
親クラス(Base)のデストラクタに virtual 付けなくても...
{
shared_ptr<Base> obj( new Derived() );
} // ~Derived() called, then ~Base() called.
~Derived() はコールされるんですね... 確認してみて驚きました。
これができる仕組みを誰か教えてください。
スマートポインタのオブジェクトは子クラスの事何も知らないのに
どうして ~Derived() のコールが可能なのでしょうか? >>950
まだ仕組みのとこまでですが理解できました。ありがとうございます。 質問ですが構造体Fooの内側に構造体Barが定義されているという入れ子になった構造体において、
Fooの外のコードでFoo::Barのサイズをsizeof()で知りたいとき、以下は正しい?
1. C++だとsizeof(Foo::Bar)と書いたらおk
2. CまたはC++でもC互換構文の範疇で済ます場合、次のどちらかの方法でしか書けない
(1) Foo::Barのインスタンスyが存在するスコープ内で、sizeof(y)と書く
(2) Fooのインスタンスxが存在するスコープ内において、Foo::Bar型のメンバyをFooが持つ
(Foo::yが定義されている)という条件の下で、sizeof(x.y)と書く ふとオモタがインスタンスの必要性は無くせるかもしれん
Foo::Bar型のメンバFoo::yが定義さえされておれば、Fooのインスタンスが無くても
sizeof(((Foo*)0)->y)
と書けばC言語で逝けるかもしれん…
スゲー気持ち悪いコードだが、、、、 >>951
あくまでコンパイル時の型で決まるだけだから要注意
例えば
class A;
class B : public A;
A* p = new B();
std::shared_ptr<A> a(p);
これだとBのデストラクタは呼ばれない なんでそんな中途半端な機能を
わざわざコストをかけて入れたんだろう >>953
Linuxカーネルとかそういう感じのマクロ満載だよ
C言語はそういうもん >>943
思い出した。
gcc や clang の拡張で良ければ複文が式になる。
だいぶん昔からある機能。
#include <vector>
#include <iostream>
int main() {
std::vector<int> foo(({int i; for(i=0; i<3; i++); i;}));
std::cout << foo.size() << std::endl;
return 0;
} >>944,945,948,959
コメントありがとうございます!
>>944,959
まずgcc拡張
>SieveDerived(int n) : Sieve<T>(({int r; while((r = index(n)) == 0) n--; r;})) { } /* HERE!! */
で問題なく動作しました
すでにgcc拡張で存在するところからみて、私の希望はあながち無謀かつ無稽なものではないことを知りほっとしました
次にラムダ式で定義して即評価する方法がみつかりました
>SieveDerived(int n) : Sieve<T>([](int n)->int{int r; while ((r = index(n)) == 0) n--; return r;}(n)) { } /* HERE!! */
これがやりたかった!とても満足しています、ありがとうございました!
今までは関数オブジェクトの糖衣構文としてしかみていなかったラムダ式を、自分の希望にあわせて(あるいはねじまげてでも)採用し、表現できるようになったのは一歩理解が深まったかと考えています
>>948
>初期化リストの中にそんなごちゃごちゃしたこと書きたい?
クラスのメソッド=メンバ関数には、クラスの提供する機能として独立性の高いもの、少なくとも二箇所で同じような処理がダブっているもの、あるいは主観的には「lemma」として成り立つものを書きたいと考えていました
一箇所でしか使わないものでも lemma 性があるのならば private メソッドとして書くのもありかと思っていますが、今回の場合は、他におなじような処理をおこなっている場所はなく、かといってメソッドとして立てるほどのことでもないので、
複数個所からコールできるメソッドにはしたくなかった、という主観がありました、そういう性質の記述ならば初期化リストにごちゃごちゃ書くのもありかと、読み手には他からコールされ得ないことが自明である点からしても
https://ideone.com/y3ROXS lambdaの即時評価はjsだと多用されているイメージ
ブロックスコープないからね >>960
> すでにgcc拡張で存在するところからみて、私の希望はあながち無謀かつ無稽なものではないことを知りほっとしました
30 年以上の実績があってもなお仕様に入らない程度に駄目なんだよ。 プライベートメンバの単体テストってみんなどうしてるのかな。 #if 0
friend test;
#endif #ifndef NDEBUG
friend struct test;
#endif namespace Method{ namespace Detail {
template<typename ReturnType, typename ... ArgTypes> struct MethodRegister{};
} }
// 文字列で呼び出すための関数を登録するためのマクロ
#define METHOD_REGISTER_WITH_NAME( NAME, FUNC, RETURNTYPE, ... ) \
namespace Method { namespace Detail { \
template<> struct MethodRegister<RETURNTYPE, __VA_ARGS__> { \
using Functional = std::function<RETURNTYPE(__VA_ARGS__)>; \
MethodRegister() { \
MethodContainer::GetInstance().Register<RETURNTYPE, __VA_ARGS__>( #FUNC, Functional( static_cast<RETURNTYPE(*)( __VA_ARGS__ )>( FUNC ) ) ); \
} \
~MethodRegister() { \
MethodContainer::GetInstance().Unregister( #FUNC ); \
} \
}; \
static MethodRegister<RETURNTYPE, __VA_ARGS__> sMethodRegister##FUNC; \
} }
void HOGE(){
std::cout << "Hello World!" << std::endl;
}
void HOGE( std::string text ){
std::cout << text << std::endl;
}
METHOD_REGISTER_METHOD( HOGE, void );
METHOD_REGISTER_METHOD( HOGE, void, std::string );
こういった形で関数を登録する用のクラスを生成し、変数として生成して管理の自動化を行いたいのですが、
関数のオーバーロードを対応しようとした所、クラスの再定義や変数の再定義、管理クラスへの重複登録等
多数の問題が出て詰まってしまいました。
こういった問題を対処するにはどうすればよいのでしょうか? >>966
>>967
リリース時に消す必要あんの? >>963
まあ、
({int r; while((r = index(n)) == 0) n--; r;})
の最後の
r;
というのが限りなく非文法的ですし プライベートメンバをテストしたくなったらそのロジックのみを非メンバ関数に切り出してテストしてるな。
まぁ、特に支障がなければ単純にpublicにするだけの時もあるけど。 templateでアクセスすると合法的にプライベートメンバにアクセスできる テストのテストが必要になるような意味のわからないテストコードはアウト
テストコードは実行せずに人が読んで理解できなければいけない >>978
どんな感じか見せていただけないでしょうか。 >>971
絶対必要でもないが
少なくともデバッグ用であることくらい
アピールしたい
//よりNDEBUGという特定ワードを使う点にも拘りがある >>979
例えばテストコードの中にループや条件分岐があるようなものはアウト ループは許してもらえませんか?
データの並びとか検査したいんで。
条件分岐はたぶんないと思います。 テスト用にいろんな複雑なテストも入れてるけど
まずいのか? Debugビルドしたら遅すぎて検証できなくて詰んだ 典型的な糞テストは、テスト対象の出力がハッシュや現在時刻などのような予測しづらいものに依存している場合に、
テストコードにテスト対象自体のロジックと似たものを書いてしまっているケースだな
原則的には、期待する出力は全てハードコードするのが正しい
難しいなら一度試しにテスト対象を実行して目視テストし、その結果をハードコードしたほうがマシ >>982
Parameterized Testsがあれば十分じゃね? >>986
期待する出力をハードコードするから
テストで「○○以上であること」って書くこと無いよね?
こういうテストケースある?言い換えるとそういうマッチャーって必要? >>987
それはまた別の話
ここで言ってるのは単体テストレベルの話だぞ クラスとかの勉強入る前にC言語でしっかり文字列処理出来るようになったほうがいい? >>995
strcpyなんて古い関数は21世紀では使えないぜ。std::stringでOK. C言語でしっかり文字列処理出来るようになったほうがいい? → いい
C++でC言語の文字列処理する? → しない >>987
逆にそういう不確定な部分とロジック部分を切り分けるのが単体テストの目的でもある。 単体テストはどんだけ単純でわかりやすいコードでテストパターンを網羅するかが肝
Google TestとかTest::MoreとかJUnit使ったらワカル このスレッドは1000を超えました。
新しいスレッドを立ててください。
life time: 41日 12時間 33分 22秒 レス数が1000を超えています。これ以上書き込みはできません。