アカウント名:
パスワード:
地獄継承クラスを見せられて俺のコードの方が綺麗だ、いやそれ違うだろう・・・とか理解できない?いや、これ有名なイディオムなんですよ・・・とか理解できない?デザインパターンっていうのが有りましてね・・・とか余りの無知に疲れる(半笑)
C++は罠が多すぎてちゃんと理解してるプログラマなんかこの世に存在しないだろ。例が悪すぎる。
C++のえらい人達ほど理論だけで実戦でコード書いてないからあてにならん。
C++ の標準化課程で、委員会の提案した仕様についてコンパイラ屋がダメ出ししてたのを見て、開かれているなと思うのと同時に、他の仕様もとりあえず動いてるだけなんじゃないかと疑うようになりましたよ。
> 他の仕様もとりあえず動いてるだけなんじゃないかと疑うようになりましたよ
実際、絶対やっちゃいけないけど、文法的には正しいとかいう機能が沢山ありますからねえ。(virtual なメソッドがあるクラスなのにデストラクタが virtual ではないとか、デストラクタ内でメンバを delete しているクラスなのにデフォルトのコピーコンストラクタを使ってるとか)
Cのポインタだってやっちゃいけない操作あるじゃんって話もあるけど、C++はCと比べても落とし穴の数が多すぎて、C以上に怖いような。超優秀なメンバーだけ揃ってる開発チームなら超強力な言語なんでしょうけど。
非常に危険なコードですよ、それ。
virtual 使ってるってことはすなわち、基底クラスへのポインタ経由であれこれ操作することを意味します。(基底クラス経由で操作する可能性がゼロなら、virtual にする必要がない)当然、delete することも想定すべきです。
例外的に決して delete されないこともあるだろうし、C++の設計思想として、少しでも効率を向上できる可能性がある場合には、そうできるようにしておくっていうのも知ってるけど、開発者の能力が揃ってないような現場を考えた場合、その設計思想が危険なコードを許す結果になってるってことは議論の余地がないと思います。
ほとんど使わない危険な機能はそもそも提供しない方が、一般の開発現場や、保守を長期にわたって行う状況では望ましいと思います。そして、C++の設計思想はそういう開発現場に向けたものではない。
> まず、私が出した例では、クラスAのデストラクタはprotectedですので、クラスBを外部から使用する限り、A*に対してdeleteすることは不可能です。
しかしクラスAのメンバ関数内で、delete することはできますよね。型安全性の保証としては不十分です。もちろん、熟練したC++プログラマのみで構成されるプロジェクトであれば、問題ありませんが。
> それはC++に求めるべきものではないです。
その点、すなわちC++はそういう安全性を求める言語ではないというのは、元から同意している点です。
ちなみに、他のオブジェクト指向言語を見ると、そもそも virtual などという予約語に
protectedな非virtualデストラクタの主な適用対象は、基底クラスにvirtual関数が全くない場合だと思います。基底クラスの分のvtableを完全に省略できることがその理由です。
この例だと基底クラスAはほかにvirtual関数を持っており(どのみちAのvtableが必要)、デストラクタを非virtualにする有難みがあまりないので、そこまでしなくてもいいのではかな(素直にAのデストラクタをvirtualにする)と私なら思います。
なお、protectedな非virtualデストラクタ自体は熟練というほどでもないテクニックだと思います。More Exceptional C++やModern C++ Designに取り上げられているようです(私は残念ながらどっちも読んだことがない)。最も単純な例がnoncopya
#2306317 のACです。
> この例だと基底クラスAはほかにvirtual関数を持っており、デストラクタを非virtualにする> 有難みがあまりないので、そこまでしなくてもいいのではかなと私なら思います。と私なら思います。
ですよね。私もそう思いますし、Effective C++ もそういう感じの趣旨だったかと思います。にも関わらず、言語仕様的には非 virtual を許してますし、Phorkさんのように、virtualメンバ関数のある基底クラスのデストラクタを非virtualにすることも実際に行っていると主張する方がいるわけです。こういう状況で、プログラマの質や意見の揃わない、ある程度大きなC++による開発プロジェクトを運営するのはなかなか大変です。
slabアロケータみたなものでnew/deleteを置き換えてない限り、new/delete自体が結構遅い処理ですから、ここで間接関数コールが発生しても、性能への影響はまず計測不能だと思うんですけどね。Phorkさんが計測した上でボトルネックとなるところだけvirutalを外しているのか、それとももともとの設計上、基底クラス経由のdeleteが発生しないのであればvirtualをつけないのかは興味があるところですが、たぶん後者かなと思ってます。
より多くのコメントがこの議論にあるかもしれませんが、JavaScriptが有効ではない環境を使用している場合、クラシックなコメントシステム(D1)に設定を変更する必要があります。
弘法筆を選ばず、アレゲはキーボードを選ぶ -- アレゲ研究家
C++なんかだと良くあるw (スコア:0)
地獄継承クラスを見せられて俺のコードの方が綺麗だ、いやそれ違うだろう・・・とか
理解できない?いや、これ有名なイディオムなんですよ・・・とか
理解できない?デザインパターンっていうのが有りましてね・・・とか
余りの無知に疲れる(半笑)
Re: (スコア:0)
C++は罠が多すぎてちゃんと理解してるプログラマなんかこの世に存在しないだろ。例が悪すぎる。
Re: (スコア:0)
Re: (スコア:0)
C++のえらい人達ほど理論だけで実戦でコード書いてないからあてにならん。
Re: (スコア:0)
C++ の標準化課程で、委員会の提案した仕様についてコンパイラ屋がダメ出ししてたのを見て、開かれているなと思うのと同時に、他の仕様もとりあえず動いてるだけなんじゃないかと疑うようになりましたよ。
Re: (スコア:0)
> 他の仕様もとりあえず動いてるだけなんじゃないかと疑うようになりましたよ
実際、絶対やっちゃいけないけど、文法的には正しいとかいう機能が沢山ありますからねえ。
(virtual なメソッドがあるクラスなのにデストラクタが virtual ではないとか、デストラクタ内でメンバを delete しているクラスなのにデフォルトのコピーコンストラクタを使ってるとか)
Cのポインタだってやっちゃいけない操作あるじゃんって話もあるけど、C++はCと比べても落とし穴の数が多すぎて、C以上に怖いような。
超優秀なメンバーだけ揃ってる開発チームなら超強力な言語なんでしょうけど。
絶対? (スコア:1)
class A {
protected:
~A() {}
public:
virtual void f() = 0;
};
class B : private A {
private:
virtual void f();
public:
A* a() { return this; }
};
とかやりませんか?
Re: (スコア:0)
非常に危険なコードですよ、それ。
Re: (スコア:1)
Re: (スコア:0)
virtual 使ってるってことはすなわち、基底クラスへのポインタ経由であれこれ操作することを意味します。
(基底クラス経由で操作する可能性がゼロなら、virtual にする必要がない)
当然、delete することも想定すべきです。
例外的に決して delete されないこともあるだろうし、C++の設計思想として、少しでも効率を向上できる
可能性がある場合には、そうできるようにしておくっていうのも知ってるけど、開発者の能力が揃ってない
ような現場を考えた場合、その設計思想が危険なコードを許す結果になってるってことは議論の余地がない
と思います。
ほとんど使わない危険な機能はそもそも提供しない方が、一般の開発現場や、保守を長期にわたって行う状況
では望ましいと思います。そして、C++の設計思想はそういう開発現場に向けたものではない。
Re: (スコア:1)
これは全くそう思いませんね。
まず、私が出した例では、クラスAのデストラクタはprotectedですので、クラスBを外部から使用する限り、A*に対してdeleteすることは不可能です。
そもそもdeleteは危険な操作です。対象となるポインタがdeleteできるものかどうかは常に注意を払われるべき問題です。deleteしてよいタイミングであるかどうかに加え、オブジェクトがnewで生成されたのか、スタック上に構築されたのか、placement newで構築されたのか、そのいずれのポインタであるかを言語上は区別できません。その判断をする能力が開発者に備わっていないというなら、deleteも生のポインタも禁止してスマートポインタ一本でやっていくほうがよほど安全でしょう。
設計思想が危険なコードを許す結果になっているのはその通りですが、その設計思想ゆえ、virtual関数を持つクラスのデストラクタは常にvirtualであるべきという主張には強く反対です。それはC++に求めるべきものではないです。
Re: (スコア:0)
> まず、私が出した例では、クラスAのデストラクタはprotectedですので、クラスBを外部から使用する限り、A*に対してdeleteすることは不可能です。
しかしクラスAのメンバ関数内で、delete することはできますよね。
型安全性の保証としては不十分です。
もちろん、熟練したC++プログラマのみで構成されるプロジェクトであれば、
問題ありませんが。
> それはC++に求めるべきものではないです。
その点、すなわちC++はそういう安全性を求める言語ではないというのは、元から同意している点です。
ちなみに、他のオブジェクト指向言語を見ると、そもそも virtual などという予約語に
Re: (スコア:2)
protectedな非virtualデストラクタの主な適用対象は、基底クラスにvirtual関数が全くない場合だと思います。基底クラスの分のvtableを完全に省略できることがその理由です。
この例だと基底クラスAはほかにvirtual関数を持っており(どのみちAのvtableが必要)、デストラクタを非virtualにする有難みがあまりないので、そこまでしなくてもいいのではかな(素直にAのデストラクタをvirtualにする)と私なら思います。
なお、protectedな非virtualデストラクタ自体は熟練というほどでもないテクニックだと思います。More Exceptional C++やModern C++ Designに取り上げられているようです(私は残念ながらどっちも読んだことがない)。最も単純な例がnoncopya
Re:絶対? (スコア:0)
#2306317 のACです。
> この例だと基底クラスAはほかにvirtual関数を持っており、デストラクタを非virtualにする
> 有難みがあまりないので、そこまでしなくてもいいのではかなと私なら思います。と私なら思います。
ですよね。
私もそう思いますし、Effective C++ もそういう感じの趣旨だったかと思います。
にも関わらず、言語仕様的には非 virtual を許してますし、Phorkさんのように、virtualメンバ関数のある
基底クラスのデストラクタを非virtualにすることも実際に行っていると主張する方がいるわけです。
こういう状況で、プログラマの質や意見の揃わない、ある程度大きなC++による開発プロジェクトを
運営するのはなかなか大変です。
slabアロケータみたなものでnew/deleteを置き換えてない限り、new/delete自体が結構遅い処理ですから、
ここで間接関数コールが発生しても、性能への影響はまず計測不能だと思うんですけどね。
Phorkさんが計測した上でボトルネックとなるところだけvirutalを外しているのか、それとも
もともとの設計上、基底クラス経由のdeleteが発生しないのであればvirtualをつけないのかは
興味があるところですが、たぶん後者かなと思ってます。