タグ付けされた質問 「virtual-functions」

オブジェクト指向プログラミングでは、仮想関数または仮想メソッドは、継承するクラス内で同じシグネチャを持つ関数によってその動作をオーバーライドできる関数またはメソッドです。この概念は、オブジェクト指向プログラミング(OOP)のポリモーフィズム部分の非常に重要な部分です。


25
C ++で仮想関数が必要なのはなぜですか?
私はC ++を学習していて、仮想関数を取得しています。 私が(本およびオンラインで)読んだことから、仮想関数は基本クラスの関数であり、派生クラスでオーバーライドできます。 しかし、この本の前半で、基本的な継承について学習するときに、を使用せずに派生クラスの基本関数をオーバーライドすることができましたvirtual。 ここで何が欠けているのですか?仮想関数には他にもあることを知っています。それは重要であると思われるので、それが正確に何であるかを明確にしたいと思います。オンラインで正解を見つけることができません。

7
オーバーライドする場合は、基本クラスの仮想関数を呼び出すことができますか?
クラスがFooあり、次のBarように設定するとします。 class Foo { public: int x; virtual void printStuff() { std::cout << x << std::endl; } }; class Bar : public Foo { public: int y; void printStuff() { // I would like to call Foo.printStuff() here... std::cout << y << std::endl; } }; コードで注釈を付けたように、オーバーライドしている基本クラスの関数を呼び出せるようにしたいと思います。Javaにはsuper.funcname()構文があります。これはC ++で可能ですか?




13
インライン仮想関数は本当にナンセンスですか?
この質問は、仮想関数をインラインにする必要がないというコードレビューコメントを受け取ったときに受けました。 インライン仮想関数は、関数がオブジェクトで直接呼び出されるシナリオで役立つと思いました。しかし、反論が私の頭に浮かびました-なぜ仮想を定義し、次にオブジェクトを使用してメソッドを呼び出す必要があるのでしょうか? とにかく展開されることがほとんどないので、インライン仮想関数を使用しないのが最善でしょうか? 分析に使用したコードスニペット: class Temp { public: virtual ~Temp() { } virtual void myVirtualFunction() const { cout<<"Temp::myVirtualFunction"<<endl; } }; class TempDerived : public Temp { public: void myVirtualFunction() const { cout<<"TempDerived::myVirtualFunction"<<endl; } }; int main(void) { TempDerived aDerivedObj; //Compiler thinks it's safe to expand the virtual functions aDerivedObj.myVirtualFunction(); //type …


15
仮想関数とパフォーマンス-C ++
私のクラス設計では、抽象クラスと仮想関数を幅広く使用しています。仮想機能がパフォーマンスに影響を与えていると感じました。これは本当ですか?しかし、このパフォーマンスの違いは顕著ではなく、時期尚早の最適化を行っているように見えます。正しい?

12
仮想関数とvtableはどのように実装されますか?
私たちは皆、C ++の仮想関数を知っていますが、それらは深いレベルでどのように実装されますか? 実行時にvtableを変更したり、直接アクセスしたりできますか? vtableはすべてのクラスに存在しますか、それとも少なくとも1つの仮想関数を持つクラスのみに存在しますか? 抽象クラスは、少なくとも1つのエントリの関数ポインタにNULLを持っているだけですか? 単一の仮想関数を使用すると、クラス全体が遅くなりますか?それとも仮想関数の呼び出しだけですか?また、仮想関数が実際に上書きされているかどうかに関係なく、速度が影響を受けますか、それとも仮想である限り、効果はありません。

6
C#インターフェイスメソッドが抽象または仮想として宣言されていないのはなぜですか?
インターフェイスのC#メソッドは、virtualキーワードを使用せずに宣言され、overrideキーワードを使用せずに派生クラスでオーバーライドされます。 これには理由がありますか?私はそれが単に言語の便宜であると思います、そして明らかにCLRはカバーの下でこれを処理する方法を知っています(メソッドはデフォルトでは仮想ではありません)が、他の技術的な理由はありますか? 以下は、派生クラスが生成するILです。 class Example : IDisposable { public void Dispose() { } } .method public hidebysig newslot virtual final instance void Dispose() cil managed { // Code size 2 (0x2) .maxstack 8 IL_0000: nop IL_0001: ret } // end of method Example::Dispose メソッドがvirtual finalILで宣言されていることに注意してください。

9
C ++クラスで仮想メソッドを使用する場合のパフォーマンスコストはどれくらいですか?
C ++クラス(またはその親クラスのいずれか)に少なくとも1つの仮想メソッドがあることは、クラスに仮想テーブルがあり、すべてのインスタンスに仮想ポインターがあることを意味します。 したがって、メモリコストは非常に明確です。最も重要なのは、インスタンスのメモリコストです(特に、インスタンスが小さい場合、たとえば、単に整数を含めることを意図している場合)。この場合、すべてのインスタンスに仮想ポインタがあると、インスタンスのサイズが2倍になる可能性があります。仮想テーブルが使用するメモリ領域。実際のメソッドコードが使用する領域と比較すると、通常は無視できると思います。 これは私に私の質問をもたらします:メソッドを仮想化するために測定可能なパフォーマンスコスト(つまり速度への影響)はありますか?すべてのメソッド呼び出し時に、実行時に仮想テーブルでルックアップが行われるため、このメソッドへの呼び出しが非常に頻繁であり、このメソッドが非常に短い場合、測定可能なパフォーマンスヒットがある可能性があります。それはプラットフォームに依存すると思いますが、誰かがいくつかのベンチマークを実行していますか? 私が尋ねている理由は、プログラマーが仮想メソッドの定義を忘れているために起こったバグに遭遇したからです。私がこの種の間違いを見たのはこれが初めてではありません。そして、私はそれが必要でないことが確実であるときに仮想キーワードを削除するのではなく、なぜ必要なときに仮想キーワードを追加するのかと考えました。パフォーマンスコストが低い場合は、チームで以下をお勧めします。デストラクタを含むすべてのメソッドをデフォルトで仮想化し、すべてのクラスで、必要な場合にのみ削除します。気が狂ってる?


9
C#がデフォルトでメソッドを非仮想として実装する理由
Javaとは異なり、C#はデフォルトでメソッドを非仮想関数として扱うのはなぜですか?他の考えられる結果よりもパフォーマンスの問題である可能性が高いですか? 既存のアーキテクチャがもたらすいくつかの利点について、Anders Hejlsbergからのパラグラフを読んだことを思い出します。しかし、副作用はどうですか?デフォルトで非仮想メソッドを持つことは本当に良いトレードオフですか?

9
C ++仮想関数を安全にオーバーライドする
仮想関数を含む基本クラスがあり、派生クラスでその関数をオーバーライドしたい。派生クラスで宣言した関数が実際に基本クラスの関数をオーバーライドするかどうかをコンパイラに確認させる方法はありますか?古い関数を上書きするのではなく、誤って新しい関数を宣言していないことを保証するマクロまたは何かを追加したいと思います。 この例を見てみましょう: class parent { public: virtual void handle_event(int something) const { // boring default code } }; class child : public parent { public: virtual void handle_event(int something) { // new exciting code } }; int main() { parent *p = new child(); p->handle_event(1); } のparent::handle_event()代わりにここで呼び出されますchild::handle_event()。これは、子のメソッドがconst宣言を欠落しているため、新しいメソッドが宣言されているためです。これは、関数名のタイプミスまたはパラメータータイプのわずかな違いの可能性もあります。また、基本クラスのインターフェイスが変更された場合や、派生クラスが変更を反映するように更新されなかった場合にも、簡単に発生する可能性があります。 この問題を回避する方法はありますか?コンパイラまたは他のツールにこれをチェックするように指示することはできますか?役立つコンパイラフラグ(できればg ++)これらの問題をどのように回避しますか?

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.