C ++ MythBusters。 仮想機能の神話

こんにちは。



前回の記事で、インライン関数を操作するときによく知られているすべての機能に出会えるわけではないことについて説明しました。 この記事では、いくつかの重要なコメントと、複数ページの紛争(さらにはホリバー)が発生しました。これは、インライン関数は一般に使用しないほうがよいという事実から始まり、標準テーマCに切り替えました。 C ++対 Java vs. C#対 PHP vs. ハスケル対 ...



今日、仮想機能の転換が来ました。 そして、まず、私の記事(前の記事と同じように)が完全であると主張しないように、すぐに予約します。 そして第二に、以前と同様に、この記事は専門家向けではありません。 すでにC ++の基本に精通しているが、経験が不十分な人、または本を読むのが好きでない人に役立ちます。



これはもはや私の仕事ではないので、誰もが仮想関数とは何か、そしてそれらがどのように使用されるかを知っていることを願っています。 C ++に関する一連の記事で、 RFryが遅かれ早かれ彼らに届くと確信しています



インラインメソッドに関する資料で神話があまり明確ではなかった場合、これで-逆に。 実際に、「神話」に移りましょう。



仮想機能と仮想キーワード


驚いたことに、私は非常に頻繁に出会って、 仮想キーワードが機能を階層の1つのレベルのみに仮想化すると信じている人(私は言うことができます、私自身も同じでした)に出会います 。 例の意味を説明します。



#include <cstdlib> #include <iostream> using std::cout; using std::endl; struct A { virtual ~A() {} virtual void foo() const { cout << "A::foo()" << endl; } virtual void bar() const { cout << "A::bar()" << endl; } void baz() const { cout << "A::baz()" << endl; } }; struct B : public A { virtual void foo() const { cout << "B::foo()" << endl; } void bar() const { cout << "B::bar()" << endl; } void baz() const { cout << "B::baz()" << endl; } }; struct C : public B { virtual void foo() const { cout << "C::foo()" << endl; } virtual void bar() const { cout << "C::bar()" << endl; } void baz() const { cout << "C::baz()" << endl; } }; int main() { cout << "pA is B:" << endl; A * pA = new B; pA->foo(); pA->bar(); pA->baz(); delete pA; cout << "\npA is C:" << endl; pA = new C; pA->foo(); pA->bar(); pA->baz(); delete pA; return EXIT_SUCCESS; } * This source code was highlighted with Source Code Highlighter .



  1. #include <cstdlib> #include <iostream> using std::cout; using std::endl; struct A { virtual ~A() {} virtual void foo() const { cout << "A::foo()" << endl; } virtual void bar() const { cout << "A::bar()" << endl; } void baz() const { cout << "A::baz()" << endl; } }; struct B : public A { virtual void foo() const { cout << "B::foo()" << endl; } void bar() const { cout << "B::bar()" << endl; } void baz() const { cout << "B::baz()" << endl; } }; struct C : public B { virtual void foo() const { cout << "C::foo()" << endl; } virtual void bar() const { cout << "C::bar()" << endl; } void baz() const { cout << "C::baz()" << endl; } }; int main() { cout << "pA is B:" << endl; A * pA = new B; pA->foo(); pA->bar(); pA->baz(); delete pA; cout << "\npA is C:" << endl; pA = new C; pA->foo(); pA->bar(); pA->baz(); delete pA; return EXIT_SUCCESS; } * This source code was highlighted with Source Code Highlighter .



  2. #include <cstdlib> #include <iostream> using std::cout; using std::endl; struct A { virtual ~A() {} virtual void foo() const { cout << "A::foo()" << endl; } virtual void bar() const { cout << "A::bar()" << endl; } void baz() const { cout << "A::baz()" << endl; } }; struct B : public A { virtual void foo() const { cout << "B::foo()" << endl; } void bar() const { cout << "B::bar()" << endl; } void baz() const { cout << "B::baz()" << endl; } }; struct C : public B { virtual void foo() const { cout << "C::foo()" << endl; } virtual void bar() const { cout << "C::bar()" << endl; } void baz() const { cout << "C::baz()" << endl; } }; int main() { cout << "pA is B:" << endl; A * pA = new B; pA->foo(); pA->bar(); pA->baz(); delete pA; cout << "\npA is C:" << endl; pA = new C; pA->foo(); pA->bar(); pA->baz(); delete pA; return EXIT_SUCCESS; } * This source code was highlighted with Source Code Highlighter .



  3. #include <cstdlib> #include <iostream> using std::cout; using std::endl; struct A { virtual ~A() {} virtual void foo() const { cout << "A::foo()" << endl; } virtual void bar() const { cout << "A::bar()" << endl; } void baz() const { cout << "A::baz()" << endl; } }; struct B : public A { virtual void foo() const { cout << "B::foo()" << endl; } void bar() const { cout << "B::bar()" << endl; } void baz() const { cout << "B::baz()" << endl; } }; struct C : public B { virtual void foo() const { cout << "C::foo()" << endl; } virtual void bar() const { cout << "C::bar()" << endl; } void baz() const { cout << "C::baz()" << endl; } }; int main() { cout << "pA is B:" << endl; A * pA = new B; pA->foo(); pA->bar(); pA->baz(); delete pA; cout << "\npA is C:" << endl; pA = new C; pA->foo(); pA->bar(); pA->baz(); delete pA; return EXIT_SUCCESS; } * This source code was highlighted with Source Code Highlighter .



  4. #include <cstdlib> #include <iostream> using std::cout; using std::endl; struct A { virtual ~A() {} virtual void foo() const { cout << "A::foo()" << endl; } virtual void bar() const { cout << "A::bar()" << endl; } void baz() const { cout << "A::baz()" << endl; } }; struct B : public A { virtual void foo() const { cout << "B::foo()" << endl; } void bar() const { cout << "B::bar()" << endl; } void baz() const { cout << "B::baz()" << endl; } }; struct C : public B { virtual void foo() const { cout << "C::foo()" << endl; } virtual void bar() const { cout << "C::bar()" << endl; } void baz() const { cout << "C::baz()" << endl; } }; int main() { cout << "pA is B:" << endl; A * pA = new B; pA->foo(); pA->bar(); pA->baz(); delete pA; cout << "\npA is C:" << endl; pA = new C; pA->foo(); pA->bar(); pA->baz(); delete pA; return EXIT_SUCCESS; } * This source code was highlighted with Source Code Highlighter .



  5. #include <cstdlib> #include <iostream> using std::cout; using std::endl; struct A { virtual ~A() {} virtual void foo() const { cout << "A::foo()" << endl; } virtual void bar() const { cout << "A::bar()" << endl; } void baz() const { cout << "A::baz()" << endl; } }; struct B : public A { virtual void foo() const { cout << "B::foo()" << endl; } void bar() const { cout << "B::bar()" << endl; } void baz() const { cout << "B::baz()" << endl; } }; struct C : public B { virtual void foo() const { cout << "C::foo()" << endl; } virtual void bar() const { cout << "C::bar()" << endl; } void baz() const { cout << "C::baz()" << endl; } }; int main() { cout << "pA is B:" << endl; A * pA = new B; pA->foo(); pA->bar(); pA->baz(); delete pA; cout << "\npA is C:" << endl; pA = new C; pA->foo(); pA->bar(); pA->baz(); delete pA; return EXIT_SUCCESS; } * This source code was highlighted with Source Code Highlighter .



  6. #include <cstdlib> #include <iostream> using std::cout; using std::endl; struct A { virtual ~A() {} virtual void foo() const { cout << "A::foo()" << endl; } virtual void bar() const { cout << "A::bar()" << endl; } void baz() const { cout << "A::baz()" << endl; } }; struct B : public A { virtual void foo() const { cout << "B::foo()" << endl; } void bar() const { cout << "B::bar()" << endl; } void baz() const { cout << "B::baz()" << endl; } }; struct C : public B { virtual void foo() const { cout << "C::foo()" << endl; } virtual void bar() const { cout << "C::bar()" << endl; } void baz() const { cout << "C::baz()" << endl; } }; int main() { cout << "pA is B:" << endl; A * pA = new B; pA->foo(); pA->bar(); pA->baz(); delete pA; cout << "\npA is C:" << endl; pA = new C; pA->foo(); pA->bar(); pA->baz(); delete pA; return EXIT_SUCCESS; } * This source code was highlighted with Source Code Highlighter .



  7. #include <cstdlib> #include <iostream> using std::cout; using std::endl; struct A { virtual ~A() {} virtual void foo() const { cout << "A::foo()" << endl; } virtual void bar() const { cout << "A::bar()" << endl; } void baz() const { cout << "A::baz()" << endl; } }; struct B : public A { virtual void foo() const { cout << "B::foo()" << endl; } void bar() const { cout << "B::bar()" << endl; } void baz() const { cout << "B::baz()" << endl; } }; struct C : public B { virtual void foo() const { cout << "C::foo()" << endl; } virtual void bar() const { cout << "C::bar()" << endl; } void baz() const { cout << "C::baz()" << endl; } }; int main() { cout << "pA is B:" << endl; A * pA = new B; pA->foo(); pA->bar(); pA->baz(); delete pA; cout << "\npA is C:" << endl; pA = new C; pA->foo(); pA->bar(); pA->baz(); delete pA; return EXIT_SUCCESS; } * This source code was highlighted with Source Code Highlighter .



  8. #include <cstdlib> #include <iostream> using std::cout; using std::endl; struct A { virtual ~A() {} virtual void foo() const { cout << "A::foo()" << endl; } virtual void bar() const { cout << "A::bar()" << endl; } void baz() const { cout << "A::baz()" << endl; } }; struct B : public A { virtual void foo() const { cout << "B::foo()" << endl; } void bar() const { cout << "B::bar()" << endl; } void baz() const { cout << "B::baz()" << endl; } }; struct C : public B { virtual void foo() const { cout << "C::foo()" << endl; } virtual void bar() const { cout << "C::bar()" << endl; } void baz() const { cout << "C::baz()" << endl; } }; int main() { cout << "pA is B:" << endl; A * pA = new B; pA->foo(); pA->bar(); pA->baz(); delete pA; cout << "\npA is C:" << endl; pA = new C; pA->foo(); pA->bar(); pA->baz(); delete pA; return EXIT_SUCCESS; } * This source code was highlighted with Source Code Highlighter .



  9. #include <cstdlib> #include <iostream> using std::cout; using std::endl; struct A { virtual ~A() {} virtual void foo() const { cout << "A::foo()" << endl; } virtual void bar() const { cout << "A::bar()" << endl; } void baz() const { cout << "A::baz()" << endl; } }; struct B : public A { virtual void foo() const { cout << "B::foo()" << endl; } void bar() const { cout << "B::bar()" << endl; } void baz() const { cout << "B::baz()" << endl; } }; struct C : public B { virtual void foo() const { cout << "C::foo()" << endl; } virtual void bar() const { cout << "C::bar()" << endl; } void baz() const { cout << "C::baz()" << endl; } }; int main() { cout << "pA is B:" << endl; A * pA = new B; pA->foo(); pA->bar(); pA->baz(); delete pA; cout << "\npA is C:" << endl; pA = new C; pA->foo(); pA->bar(); pA->baz(); delete pA; return EXIT_SUCCESS; } * This source code was highlighted with Source Code Highlighter .



  10. #include <cstdlib> #include <iostream> using std::cout; using std::endl; struct A { virtual ~A() {} virtual void foo() const { cout << "A::foo()" << endl; } virtual void bar() const { cout << "A::bar()" << endl; } void baz() const { cout << "A::baz()" << endl; } }; struct B : public A { virtual void foo() const { cout << "B::foo()" << endl; } void bar() const { cout << "B::bar()" << endl; } void baz() const { cout << "B::baz()" << endl; } }; struct C : public B { virtual void foo() const { cout << "C::foo()" << endl; } virtual void bar() const { cout << "C::bar()" << endl; } void baz() const { cout << "C::baz()" << endl; } }; int main() { cout << "pA is B:" << endl; A * pA = new B; pA->foo(); pA->bar(); pA->baz(); delete pA; cout << "\npA is C:" << endl; pA = new C; pA->foo(); pA->bar(); pA->baz(); delete pA; return EXIT_SUCCESS; } * This source code was highlighted with Source Code Highlighter .



  11. #include <cstdlib> #include <iostream> using std::cout; using std::endl; struct A { virtual ~A() {} virtual void foo() const { cout << "A::foo()" << endl; } virtual void bar() const { cout << "A::bar()" << endl; } void baz() const { cout << "A::baz()" << endl; } }; struct B : public A { virtual void foo() const { cout << "B::foo()" << endl; } void bar() const { cout << "B::bar()" << endl; } void baz() const { cout << "B::baz()" << endl; } }; struct C : public B { virtual void foo() const { cout << "C::foo()" << endl; } virtual void bar() const { cout << "C::bar()" << endl; } void baz() const { cout << "C::baz()" << endl; } }; int main() { cout << "pA is B:" << endl; A * pA = new B; pA->foo(); pA->bar(); pA->baz(); delete pA; cout << "\npA is C:" << endl; pA = new C; pA->foo(); pA->bar(); pA->baz(); delete pA; return EXIT_SUCCESS; } * This source code was highlighted with Source Code Highlighter .



  12. #include <cstdlib> #include <iostream> using std::cout; using std::endl; struct A { virtual ~A() {} virtual void foo() const { cout << "A::foo()" << endl; } virtual void bar() const { cout << "A::bar()" << endl; } void baz() const { cout << "A::baz()" << endl; } }; struct B : public A { virtual void foo() const { cout << "B::foo()" << endl; } void bar() const { cout << "B::bar()" << endl; } void baz() const { cout << "B::baz()" << endl; } }; struct C : public B { virtual void foo() const { cout << "C::foo()" << endl; } virtual void bar() const { cout << "C::bar()" << endl; } void baz() const { cout << "C::baz()" << endl; } }; int main() { cout << "pA is B:" << endl; A * pA = new B; pA->foo(); pA->bar(); pA->baz(); delete pA; cout << "\npA is C:" << endl; pA = new C; pA->foo(); pA->bar(); pA->baz(); delete pA; return EXIT_SUCCESS; } * This source code was highlighted with Source Code Highlighter .



  13. #include <cstdlib> #include <iostream> using std::cout; using std::endl; struct A { virtual ~A() {} virtual void foo() const { cout << "A::foo()" << endl; } virtual void bar() const { cout << "A::bar()" << endl; } void baz() const { cout << "A::baz()" << endl; } }; struct B : public A { virtual void foo() const { cout << "B::foo()" << endl; } void bar() const { cout << "B::bar()" << endl; } void baz() const { cout << "B::baz()" << endl; } }; struct C : public B { virtual void foo() const { cout << "C::foo()" << endl; } virtual void bar() const { cout << "C::bar()" << endl; } void baz() const { cout << "C::baz()" << endl; } }; int main() { cout << "pA is B:" << endl; A * pA = new B; pA->foo(); pA->bar(); pA->baz(); delete pA; cout << "\npA is C:" << endl; pA = new C; pA->foo(); pA->bar(); pA->baz(); delete pA; return EXIT_SUCCESS; } * This source code was highlighted with Source Code Highlighter .



  14. #include <cstdlib> #include <iostream> using std::cout; using std::endl; struct A { virtual ~A() {} virtual void foo() const { cout << "A::foo()" << endl; } virtual void bar() const { cout << "A::bar()" << endl; } void baz() const { cout << "A::baz()" << endl; } }; struct B : public A { virtual void foo() const { cout << "B::foo()" << endl; } void bar() const { cout << "B::bar()" << endl; } void baz() const { cout << "B::baz()" << endl; } }; struct C : public B { virtual void foo() const { cout << "C::foo()" << endl; } virtual void bar() const { cout << "C::bar()" << endl; } void baz() const { cout << "C::baz()" << endl; } }; int main() { cout << "pA is B:" << endl; A * pA = new B; pA->foo(); pA->bar(); pA->baz(); delete pA; cout << "\npA is C:" << endl; pA = new C; pA->foo(); pA->bar(); pA->baz(); delete pA; return EXIT_SUCCESS; } * This source code was highlighted with Source Code Highlighter .



  15. #include <cstdlib> #include <iostream> using std::cout; using std::endl; struct A { virtual ~A() {} virtual void foo() const { cout << "A::foo()" << endl; } virtual void bar() const { cout << "A::bar()" << endl; } void baz() const { cout << "A::baz()" << endl; } }; struct B : public A { virtual void foo() const { cout << "B::foo()" << endl; } void bar() const { cout << "B::bar()" << endl; } void baz() const { cout << "B::baz()" << endl; } }; struct C : public B { virtual void foo() const { cout << "C::foo()" << endl; } virtual void bar() const { cout << "C::bar()" << endl; } void baz() const { cout << "C::baz()" << endl; } }; int main() { cout << "pA is B:" << endl; A * pA = new B; pA->foo(); pA->bar(); pA->baz(); delete pA; cout << "\npA is C:" << endl; pA = new C; pA->foo(); pA->bar(); pA->baz(); delete pA; return EXIT_SUCCESS; } * This source code was highlighted with Source Code Highlighter .



  16. #include <cstdlib> #include <iostream> using std::cout; using std::endl; struct A { virtual ~A() {} virtual void foo() const { cout << "A::foo()" << endl; } virtual void bar() const { cout << "A::bar()" << endl; } void baz() const { cout << "A::baz()" << endl; } }; struct B : public A { virtual void foo() const { cout << "B::foo()" << endl; } void bar() const { cout << "B::bar()" << endl; } void baz() const { cout << "B::baz()" << endl; } }; struct C : public B { virtual void foo() const { cout << "C::foo()" << endl; } virtual void bar() const { cout << "C::bar()" << endl; } void baz() const { cout << "C::baz()" << endl; } }; int main() { cout << "pA is B:" << endl; A * pA = new B; pA->foo(); pA->bar(); pA->baz(); delete pA; cout << "\npA is C:" << endl; pA = new C; pA->foo(); pA->bar(); pA->baz(); delete pA; return EXIT_SUCCESS; } * This source code was highlighted with Source Code Highlighter .



  17. #include <cstdlib> #include <iostream> using std::cout; using std::endl; struct A { virtual ~A() {} virtual void foo() const { cout << "A::foo()" << endl; } virtual void bar() const { cout << "A::bar()" << endl; } void baz() const { cout << "A::baz()" << endl; } }; struct B : public A { virtual void foo() const { cout << "B::foo()" << endl; } void bar() const { cout << "B::bar()" << endl; } void baz() const { cout << "B::baz()" << endl; } }; struct C : public B { virtual void foo() const { cout << "C::foo()" << endl; } virtual void bar() const { cout << "C::bar()" << endl; } void baz() const { cout << "C::baz()" << endl; } }; int main() { cout << "pA is B:" << endl; A * pA = new B; pA->foo(); pA->bar(); pA->baz(); delete pA; cout << "\npA is C:" << endl; pA = new C; pA->foo(); pA->bar(); pA->baz(); delete pA; return EXIT_SUCCESS; } * This source code was highlighted with Source Code Highlighter .



  18. #include <cstdlib> #include <iostream> using std::cout; using std::endl; struct A { virtual ~A() {} virtual void foo() const { cout << "A::foo()" << endl; } virtual void bar() const { cout << "A::bar()" << endl; } void baz() const { cout << "A::baz()" << endl; } }; struct B : public A { virtual void foo() const { cout << "B::foo()" << endl; } void bar() const { cout << "B::bar()" << endl; } void baz() const { cout << "B::baz()" << endl; } }; struct C : public B { virtual void foo() const { cout << "C::foo()" << endl; } virtual void bar() const { cout << "C::bar()" << endl; } void baz() const { cout << "C::baz()" << endl; } }; int main() { cout << "pA is B:" << endl; A * pA = new B; pA->foo(); pA->bar(); pA->baz(); delete pA; cout << "\npA is C:" << endl; pA = new C; pA->foo(); pA->bar(); pA->baz(); delete pA; return EXIT_SUCCESS; } * This source code was highlighted with Source Code Highlighter .



  19. #include <cstdlib> #include <iostream> using std::cout; using std::endl; struct A { virtual ~A() {} virtual void foo() const { cout << "A::foo()" << endl; } virtual void bar() const { cout << "A::bar()" << endl; } void baz() const { cout << "A::baz()" << endl; } }; struct B : public A { virtual void foo() const { cout << "B::foo()" << endl; } void bar() const { cout << "B::bar()" << endl; } void baz() const { cout << "B::baz()" << endl; } }; struct C : public B { virtual void foo() const { cout << "C::foo()" << endl; } virtual void bar() const { cout << "C::bar()" << endl; } void baz() const { cout << "C::baz()" << endl; } }; int main() { cout << "pA is B:" << endl; A * pA = new B; pA->foo(); pA->bar(); pA->baz(); delete pA; cout << "\npA is C:" << endl; pA = new C; pA->foo(); pA->bar(); pA->baz(); delete pA; return EXIT_SUCCESS; } * This source code was highlighted with Source Code Highlighter .



  20. #include <cstdlib> #include <iostream> using std::cout; using std::endl; struct A { virtual ~A() {} virtual void foo() const { cout << "A::foo()" << endl; } virtual void bar() const { cout << "A::bar()" << endl; } void baz() const { cout << "A::baz()" << endl; } }; struct B : public A { virtual void foo() const { cout << "B::foo()" << endl; } void bar() const { cout << "B::bar()" << endl; } void baz() const { cout << "B::baz()" << endl; } }; struct C : public B { virtual void foo() const { cout << "C::foo()" << endl; } virtual void bar() const { cout << "C::bar()" << endl; } void baz() const { cout << "C::baz()" << endl; } }; int main() { cout << "pA is B:" << endl; A * pA = new B; pA->foo(); pA->bar(); pA->baz(); delete pA; cout << "\npA is C:" << endl; pA = new C; pA->foo(); pA->bar(); pA->baz(); delete pA; return EXIT_SUCCESS; } * This source code was highlighted with Source Code Highlighter .



  21. #include <cstdlib> #include <iostream> using std::cout; using std::endl; struct A { virtual ~A() {} virtual void foo() const { cout << "A::foo()" << endl; } virtual void bar() const { cout << "A::bar()" << endl; } void baz() const { cout << "A::baz()" << endl; } }; struct B : public A { virtual void foo() const { cout << "B::foo()" << endl; } void bar() const { cout << "B::bar()" << endl; } void baz() const { cout << "B::baz()" << endl; } }; struct C : public B { virtual void foo() const { cout << "C::foo()" << endl; } virtual void bar() const { cout << "C::bar()" << endl; } void baz() const { cout << "C::baz()" << endl; } }; int main() { cout << "pA is B:" << endl; A * pA = new B; pA->foo(); pA->bar(); pA->baz(); delete pA; cout << "\npA is C:" << endl; pA = new C; pA->foo(); pA->bar(); pA->baz(); delete pA; return EXIT_SUCCESS; } * This source code was highlighted with Source Code Highlighter .



  22. #include <cstdlib> #include <iostream> using std::cout; using std::endl; struct A { virtual ~A() {} virtual void foo() const { cout << "A::foo()" << endl; } virtual void bar() const { cout << "A::bar()" << endl; } void baz() const { cout << "A::baz()" << endl; } }; struct B : public A { virtual void foo() const { cout << "B::foo()" << endl; } void bar() const { cout << "B::bar()" << endl; } void baz() const { cout << "B::baz()" << endl; } }; struct C : public B { virtual void foo() const { cout << "C::foo()" << endl; } virtual void bar() const { cout << "C::bar()" << endl; } void baz() const { cout << "C::baz()" << endl; } }; int main() { cout << "pA is B:" << endl; A * pA = new B; pA->foo(); pA->bar(); pA->baz(); delete pA; cout << "\npA is C:" << endl; pA = new C; pA->foo(); pA->bar(); pA->baz(); delete pA; return EXIT_SUCCESS; } * This source code was highlighted with Source Code Highlighter .



  23. #include <cstdlib> #include <iostream> using std::cout; using std::endl; struct A { virtual ~A() {} virtual void foo() const { cout << "A::foo()" << endl; } virtual void bar() const { cout << "A::bar()" << endl; } void baz() const { cout << "A::baz()" << endl; } }; struct B : public A { virtual void foo() const { cout << "B::foo()" << endl; } void bar() const { cout << "B::bar()" << endl; } void baz() const { cout << "B::baz()" << endl; } }; struct C : public B { virtual void foo() const { cout << "C::foo()" << endl; } virtual void bar() const { cout << "C::bar()" << endl; } void baz() const { cout << "C::baz()" << endl; } }; int main() { cout << "pA is B:" << endl; A * pA = new B; pA->foo(); pA->bar(); pA->baz(); delete pA; cout << "\npA is C:" << endl; pA = new C; pA->foo(); pA->bar(); pA->baz(); delete pA; return EXIT_SUCCESS; } * This source code was highlighted with Source Code Highlighter .



  24. #include <cstdlib> #include <iostream> using std::cout; using std::endl; struct A { virtual ~A() {} virtual void foo() const { cout << "A::foo()" << endl; } virtual void bar() const { cout << "A::bar()" << endl; } void baz() const { cout << "A::baz()" << endl; } }; struct B : public A { virtual void foo() const { cout << "B::foo()" << endl; } void bar() const { cout << "B::bar()" << endl; } void baz() const { cout << "B::baz()" << endl; } }; struct C : public B { virtual void foo() const { cout << "C::foo()" << endl; } virtual void bar() const { cout << "C::bar()" << endl; } void baz() const { cout << "C::baz()" << endl; } }; int main() { cout << "pA is B:" << endl; A * pA = new B; pA->foo(); pA->bar(); pA->baz(); delete pA; cout << "\npA is C:" << endl; pA = new C; pA->foo(); pA->bar(); pA->baz(); delete pA; return EXIT_SUCCESS; } * This source code was highlighted with Source Code Highlighter .



  25. #include <cstdlib> #include <iostream> using std::cout; using std::endl; struct A { virtual ~A() {} virtual void foo() const { cout << "A::foo()" << endl; } virtual void bar() const { cout << "A::bar()" << endl; } void baz() const { cout << "A::baz()" << endl; } }; struct B : public A { virtual void foo() const { cout << "B::foo()" << endl; } void bar() const { cout << "B::bar()" << endl; } void baz() const { cout << "B::baz()" << endl; } }; struct C : public B { virtual void foo() const { cout << "C::foo()" << endl; } virtual void bar() const { cout << "C::bar()" << endl; } void baz() const { cout << "C::baz()" << endl; } }; int main() { cout << "pA is B:" << endl; A * pA = new B; pA->foo(); pA->bar(); pA->baz(); delete pA; cout << "\npA is C:" << endl; pA = new C; pA->foo(); pA->bar(); pA->baz(); delete pA; return EXIT_SUCCESS; } * This source code was highlighted with Source Code Highlighter .



  26. #include <cstdlib> #include <iostream> using std::cout; using std::endl; struct A { virtual ~A() {} virtual void foo() const { cout << "A::foo()" << endl; } virtual void bar() const { cout << "A::bar()" << endl; } void baz() const { cout << "A::baz()" << endl; } }; struct B : public A { virtual void foo() const { cout << "B::foo()" << endl; } void bar() const { cout << "B::bar()" << endl; } void baz() const { cout << "B::baz()" << endl; } }; struct C : public B { virtual void foo() const { cout << "C::foo()" << endl; } virtual void bar() const { cout << "C::bar()" << endl; } void baz() const { cout << "C::baz()" << endl; } }; int main() { cout << "pA is B:" << endl; A * pA = new B; pA->foo(); pA->bar(); pA->baz(); delete pA; cout << "\npA is C:" << endl; pA = new C; pA->foo(); pA->bar(); pA->baz(); delete pA; return EXIT_SUCCESS; } * This source code was highlighted with Source Code Highlighter .



  27. #include <cstdlib> #include <iostream> using std::cout; using std::endl; struct A { virtual ~A() {} virtual void foo() const { cout << "A::foo()" << endl; } virtual void bar() const { cout << "A::bar()" << endl; } void baz() const { cout << "A::baz()" << endl; } }; struct B : public A { virtual void foo() const { cout << "B::foo()" << endl; } void bar() const { cout << "B::bar()" << endl; } void baz() const { cout << "B::baz()" << endl; } }; struct C : public B { virtual void foo() const { cout << "C::foo()" << endl; } virtual void bar() const { cout << "C::bar()" << endl; } void baz() const { cout << "C::baz()" << endl; } }; int main() { cout << "pA is B:" << endl; A * pA = new B; pA->foo(); pA->bar(); pA->baz(); delete pA; cout << "\npA is C:" << endl; pA = new C; pA->foo(); pA->bar(); pA->baz(); delete pA; return EXIT_SUCCESS; } * This source code was highlighted with Source Code Highlighter .



  28. #include <cstdlib> #include <iostream> using std::cout; using std::endl; struct A { virtual ~A() {} virtual void foo() const { cout << "A::foo()" << endl; } virtual void bar() const { cout << "A::bar()" << endl; } void baz() const { cout << "A::baz()" << endl; } }; struct B : public A { virtual void foo() const { cout << "B::foo()" << endl; } void bar() const { cout << "B::bar()" << endl; } void baz() const { cout << "B::baz()" << endl; } }; struct C : public B { virtual void foo() const { cout << "C::foo()" << endl; } virtual void bar() const { cout << "C::bar()" << endl; } void baz() const { cout << "C::baz()" << endl; } }; int main() { cout << "pA is B:" << endl; A * pA = new B; pA->foo(); pA->bar(); pA->baz(); delete pA; cout << "\npA is C:" << endl; pA = new C; pA->foo(); pA->bar(); pA->baz(); delete pA; return EXIT_SUCCESS; } * This source code was highlighted with Source Code Highlighter .



  29. #include <cstdlib> #include <iostream> using std::cout; using std::endl; struct A { virtual ~A() {} virtual void foo() const { cout << "A::foo()" << endl; } virtual void bar() const { cout << "A::bar()" << endl; } void baz() const { cout << "A::baz()" << endl; } }; struct B : public A { virtual void foo() const { cout << "B::foo()" << endl; } void bar() const { cout << "B::bar()" << endl; } void baz() const { cout << "B::baz()" << endl; } }; struct C : public B { virtual void foo() const { cout << "C::foo()" << endl; } virtual void bar() const { cout << "C::bar()" << endl; } void baz() const { cout << "C::baz()" << endl; } }; int main() { cout << "pA is B:" << endl; A * pA = new B; pA->foo(); pA->bar(); pA->baz(); delete pA; cout << "\npA is C:" << endl; pA = new C; pA->foo(); pA->bar(); pA->baz(); delete pA; return EXIT_SUCCESS; } * This source code was highlighted with Source Code Highlighter .



  30. #include <cstdlib> #include <iostream> using std::cout; using std::endl; struct A { virtual ~A() {} virtual void foo() const { cout << "A::foo()" << endl; } virtual void bar() const { cout << "A::bar()" << endl; } void baz() const { cout << "A::baz()" << endl; } }; struct B : public A { virtual void foo() const { cout << "B::foo()" << endl; } void bar() const { cout << "B::bar()" << endl; } void baz() const { cout << "B::baz()" << endl; } }; struct C : public B { virtual void foo() const { cout << "C::foo()" << endl; } virtual void bar() const { cout << "C::bar()" << endl; } void baz() const { cout << "C::baz()" << endl; } }; int main() { cout << "pA is B:" << endl; A * pA = new B; pA->foo(); pA->bar(); pA->baz(); delete pA; cout << "\npA is C:" << endl; pA = new C; pA->foo(); pA->bar(); pA->baz(); delete pA; return EXIT_SUCCESS; } * This source code was highlighted with Source Code Highlighter .



  31. #include <cstdlib> #include <iostream> using std::cout; using std::endl; struct A { virtual ~A() {} virtual void foo() const { cout << "A::foo()" << endl; } virtual void bar() const { cout << "A::bar()" << endl; } void baz() const { cout << "A::baz()" << endl; } }; struct B : public A { virtual void foo() const { cout << "B::foo()" << endl; } void bar() const { cout << "B::bar()" << endl; } void baz() const { cout << "B::baz()" << endl; } }; struct C : public B { virtual void foo() const { cout << "C::foo()" << endl; } virtual void bar() const { cout << "C::bar()" << endl; } void baz() const { cout << "C::baz()" << endl; } }; int main() { cout << "pA is B:" << endl; A * pA = new B; pA->foo(); pA->bar(); pA->baz(); delete pA; cout << "\npA is C:" << endl; pA = new C; pA->foo(); pA->bar(); pA->baz(); delete pA; return EXIT_SUCCESS; } * This source code was highlighted with Source Code Highlighter .



  32. #include <cstdlib> #include <iostream> using std::cout; using std::endl; struct A { virtual ~A() {} virtual void foo() const { cout << "A::foo()" << endl; } virtual void bar() const { cout << "A::bar()" << endl; } void baz() const { cout << "A::baz()" << endl; } }; struct B : public A { virtual void foo() const { cout << "B::foo()" << endl; } void bar() const { cout << "B::bar()" << endl; } void baz() const { cout << "B::baz()" << endl; } }; struct C : public B { virtual void foo() const { cout << "C::foo()" << endl; } virtual void bar() const { cout << "C::bar()" << endl; } void baz() const { cout << "C::baz()" << endl; } }; int main() { cout << "pA is B:" << endl; A * pA = new B; pA->foo(); pA->bar(); pA->baz(); delete pA; cout << "\npA is C:" << endl; pA = new C; pA->foo(); pA->bar(); pA->baz(); delete pA; return EXIT_SUCCESS; } * This source code was highlighted with Source Code Highlighter .



  33. #include <cstdlib> #include <iostream> using std::cout; using std::endl; struct A { virtual ~A() {} virtual void foo() const { cout << "A::foo()" << endl; } virtual void bar() const { cout << "A::bar()" << endl; } void baz() const { cout << "A::baz()" << endl; } }; struct B : public A { virtual void foo() const { cout << "B::foo()" << endl; } void bar() const { cout << "B::bar()" << endl; } void baz() const { cout << "B::baz()" << endl; } }; struct C : public B { virtual void foo() const { cout << "C::foo()" << endl; } virtual void bar() const { cout << "C::bar()" << endl; } void baz() const { cout << "C::baz()" << endl; } }; int main() { cout << "pA is B:" << endl; A * pA = new B; pA->foo(); pA->bar(); pA->baz(); delete pA; cout << "\npA is C:" << endl; pA = new C; pA->foo(); pA->bar(); pA->baz(); delete pA; return EXIT_SUCCESS; } * This source code was highlighted with Source Code Highlighter .



  34. #include <cstdlib> #include <iostream> using std::cout; using std::endl; struct A { virtual ~A() {} virtual void foo() const { cout << "A::foo()" << endl; } virtual void bar() const { cout << "A::bar()" << endl; } void baz() const { cout << "A::baz()" << endl; } }; struct B : public A { virtual void foo() const { cout << "B::foo()" << endl; } void bar() const { cout << "B::bar()" << endl; } void baz() const { cout << "B::baz()" << endl; } }; struct C : public B { virtual void foo() const { cout << "C::foo()" << endl; } virtual void bar() const { cout << "C::bar()" << endl; } void baz() const { cout << "C::baz()" << endl; } }; int main() { cout << "pA is B:" << endl; A * pA = new B; pA->foo(); pA->bar(); pA->baz(); delete pA; cout << "\npA is C:" << endl; pA = new C; pA->foo(); pA->bar(); pA->baz(); delete pA; return EXIT_SUCCESS; } * This source code was highlighted with Source Code Highlighter .



  35. #include <cstdlib> #include <iostream> using std::cout; using std::endl; struct A { virtual ~A() {} virtual void foo() const { cout << "A::foo()" << endl; } virtual void bar() const { cout << "A::bar()" << endl; } void baz() const { cout << "A::baz()" << endl; } }; struct B : public A { virtual void foo() const { cout << "B::foo()" << endl; } void bar() const { cout << "B::bar()" << endl; } void baz() const { cout << "B::baz()" << endl; } }; struct C : public B { virtual void foo() const { cout << "C::foo()" << endl; } virtual void bar() const { cout << "C::bar()" << endl; } void baz() const { cout << "C::baz()" << endl; } }; int main() { cout << "pA is B:" << endl; A * pA = new B; pA->foo(); pA->bar(); pA->baz(); delete pA; cout << "\npA is C:" << endl; pA = new C; pA->foo(); pA->bar(); pA->baz(); delete pA; return EXIT_SUCCESS; } * This source code was highlighted with Source Code Highlighter .



  36. #include <cstdlib> #include <iostream> using std::cout; using std::endl; struct A { virtual ~A() {} virtual void foo() const { cout << "A::foo()" << endl; } virtual void bar() const { cout << "A::bar()" << endl; } void baz() const { cout << "A::baz()" << endl; } }; struct B : public A { virtual void foo() const { cout << "B::foo()" << endl; } void bar() const { cout << "B::bar()" << endl; } void baz() const { cout << "B::baz()" << endl; } }; struct C : public B { virtual void foo() const { cout << "C::foo()" << endl; } virtual void bar() const { cout << "C::bar()" << endl; } void baz() const { cout << "C::baz()" << endl; } }; int main() { cout << "pA is B:" << endl; A * pA = new B; pA->foo(); pA->bar(); pA->baz(); delete pA; cout << "\npA is C:" << endl; pA = new C; pA->foo(); pA->bar(); pA->baz(); delete pA; return EXIT_SUCCESS; } * This source code was highlighted with Source Code Highlighter .



  37. #include <cstdlib> #include <iostream> using std::cout; using std::endl; struct A { virtual ~A() {} virtual void foo() const { cout << "A::foo()" << endl; } virtual void bar() const { cout << "A::bar()" << endl; } void baz() const { cout << "A::baz()" << endl; } }; struct B : public A { virtual void foo() const { cout << "B::foo()" << endl; } void bar() const { cout << "B::bar()" << endl; } void baz() const { cout << "B::baz()" << endl; } }; struct C : public B { virtual void foo() const { cout << "C::foo()" << endl; } virtual void bar() const { cout << "C::bar()" << endl; } void baz() const { cout << "C::baz()" << endl; } }; int main() { cout << "pA is B:" << endl; A * pA = new B; pA->foo(); pA->bar(); pA->baz(); delete pA; cout << "\npA is C:" << endl; pA = new C; pA->foo(); pA->bar(); pA->baz(); delete pA; return EXIT_SUCCESS; } * This source code was highlighted with Source Code Highlighter .



#include <cstdlib> #include <iostream> using std::cout; using std::endl; struct A { virtual ~A() {} virtual void foo() const { cout << "A::foo()" << endl; } virtual void bar() const { cout << "A::bar()" << endl; } void baz() const { cout << "A::baz()" << endl; } }; struct B : public A { virtual void foo() const { cout << "B::foo()" << endl; } void bar() const { cout << "B::bar()" << endl; } void baz() const { cout << "B::baz()" << endl; } }; struct C : public B { virtual void foo() const { cout << "C::foo()" << endl; } virtual void bar() const { cout << "C::bar()" << endl; } void baz() const { cout << "C::baz()" << endl; } }; int main() { cout << "pA is B:" << endl; A * pA = new B; pA->foo(); pA->bar(); pA->baz(); delete pA; cout << "\npA is C:" << endl; pA = new C; pA->foo(); pA->bar(); pA->baz(); delete pA; return EXIT_SUCCESS; } * This source code was highlighted with Source Code Highlighter .







したがって、単純なクラス階層があります。 各クラスでは、 foo()bar() 、およびbaz()の 3つのメソッドが定義されています。 神話の影響下にある人々の間違った論理を考えてください:

ポインターpAがタイプBのオブジェクトを指すとき、結論が得られます。

pAはB:

B :: foo()//親クラスAではfoo()メソッドがvirtualとしてマークされているため

B :: bar()//親クラスAでは、bar()メソッドがvirtualとしてマークされているため

A :: baz()//親クラスAでは、baz()メソッドはvirtualとしてマークされていないため


ポインターpAがタイプCのオブジェクトを指すとき、結論が得られます。

pAはC:

C :: foo()//親クラスBではfoo()メソッドがvirtualとしてマークされているため

B :: bar()//親クラスBではbar()メソッドが仮想としてマークされていないため、

//ただし、クラスAで仮想としてマークされ、使用するポインタ

A :: baz()//クラスAではbaz()メソッドが仮想としてマークされていないため




非仮想関数baz()を使用すると、すべてが明確になります。 しかし、仮想関数を呼び出すロジックには問題があります。 実際のところ、結論は次のようになると言う価値はないと思います。



pAはB:

B :: foo()

B ::バー()

A :: baz()



pAはC:

C :: foo()

C ::バー()

A :: baz()




結論: 仮想関数は階層の最後まで仮想になり、 仮想キーワードは初めてのみ「キー」となり、次回はプログラマーの利便性のために純粋に有益な関数を実行します



これが起こる理由を理解するには、仮想機能のメカニズムがどのように機能するかを理解する必要があります。



アーリーバインディングとレイトバインディング。 仮想関数表


バインディングは、関数呼び出しから呼び出しへのマッピングです。 C ++では、すべての関数はデフォルトで事前バインディングに設定されます。つまり、コンパイラーとリンカーは、プログラムの開始前にどの関数を呼び出すかを決定します。 仮想関数には遅延バインディングがあります 。つまり、関数が呼び出されると、プログラム実行段階で目的の本体が選択されます。



仮想キーワードを満たしたコンパイラは、このメソッドにレイトバインディングを使用する必要があることに注意します。最初に、クラスの仮想関数のテーブルを作成し、プログラマに隠された新しいメンバー-このテーブルへのポインタを追加します。 (実際、私の知る限り、言語標準は仮想関数のメカニズムの実装方法を規定していませんが、仮想テーブルに基づく実装は事実上の標準になりました。) この校正コードを検討してください。



#include <cstdlib> #include <iostream> struct Empty {}; struct EmptyVirt { virtual ~EmptyVirt(){} }; struct NotEmpty { int m_i; }; struct NotEmptyVirt { virtual ~NotEmptyVirt() {} int m_i; }; struct NotEmptyNonVirt { void foo() const {} int m_i; }; int main() { std::cout << sizeof (Empty) << std::endl; std::cout << sizeof (EmptyVirt) << std::endl; std::cout << sizeof (NotEmpty) << std::endl; std::cout << sizeof (NotEmptyVirt) << std::endl; std::cout << sizeof (NotEmptyNonVirt) << std::endl; return EXIT_SUCCESS; } * This source code was highlighted with Source Code Highlighter .



  1. #include <cstdlib> #include <iostream> struct Empty {}; struct EmptyVirt { virtual ~EmptyVirt(){} }; struct NotEmpty { int m_i; }; struct NotEmptyVirt { virtual ~NotEmptyVirt() {} int m_i; }; struct NotEmptyNonVirt { void foo() const {} int m_i; }; int main() { std::cout << sizeof (Empty) << std::endl; std::cout << sizeof (EmptyVirt) << std::endl; std::cout << sizeof (NotEmpty) << std::endl; std::cout << sizeof (NotEmptyVirt) << std::endl; std::cout << sizeof (NotEmptyNonVirt) << std::endl; return EXIT_SUCCESS; } * This source code was highlighted with Source Code Highlighter .



  2. #include <cstdlib> #include <iostream> struct Empty {}; struct EmptyVirt { virtual ~EmptyVirt(){} }; struct NotEmpty { int m_i; }; struct NotEmptyVirt { virtual ~NotEmptyVirt() {} int m_i; }; struct NotEmptyNonVirt { void foo() const {} int m_i; }; int main() { std::cout << sizeof (Empty) << std::endl; std::cout << sizeof (EmptyVirt) << std::endl; std::cout << sizeof (NotEmpty) << std::endl; std::cout << sizeof (NotEmptyVirt) << std::endl; std::cout << sizeof (NotEmptyNonVirt) << std::endl; return EXIT_SUCCESS; } * This source code was highlighted with Source Code Highlighter .



  3. #include <cstdlib> #include <iostream> struct Empty {}; struct EmptyVirt { virtual ~EmptyVirt(){} }; struct NotEmpty { int m_i; }; struct NotEmptyVirt { virtual ~NotEmptyVirt() {} int m_i; }; struct NotEmptyNonVirt { void foo() const {} int m_i; }; int main() { std::cout << sizeof (Empty) << std::endl; std::cout << sizeof (EmptyVirt) << std::endl; std::cout << sizeof (NotEmpty) << std::endl; std::cout << sizeof (NotEmptyVirt) << std::endl; std::cout << sizeof (NotEmptyNonVirt) << std::endl; return EXIT_SUCCESS; } * This source code was highlighted with Source Code Highlighter .



  4. #include <cstdlib> #include <iostream> struct Empty {}; struct EmptyVirt { virtual ~EmptyVirt(){} }; struct NotEmpty { int m_i; }; struct NotEmptyVirt { virtual ~NotEmptyVirt() {} int m_i; }; struct NotEmptyNonVirt { void foo() const {} int m_i; }; int main() { std::cout << sizeof (Empty) << std::endl; std::cout << sizeof (EmptyVirt) << std::endl; std::cout << sizeof (NotEmpty) << std::endl; std::cout << sizeof (NotEmptyVirt) << std::endl; std::cout << sizeof (NotEmptyNonVirt) << std::endl; return EXIT_SUCCESS; } * This source code was highlighted with Source Code Highlighter .



  5. #include <cstdlib> #include <iostream> struct Empty {}; struct EmptyVirt { virtual ~EmptyVirt(){} }; struct NotEmpty { int m_i; }; struct NotEmptyVirt { virtual ~NotEmptyVirt() {} int m_i; }; struct NotEmptyNonVirt { void foo() const {} int m_i; }; int main() { std::cout << sizeof (Empty) << std::endl; std::cout << sizeof (EmptyVirt) << std::endl; std::cout << sizeof (NotEmpty) << std::endl; std::cout << sizeof (NotEmptyVirt) << std::endl; std::cout << sizeof (NotEmptyNonVirt) << std::endl; return EXIT_SUCCESS; } * This source code was highlighted with Source Code Highlighter .



  6. #include <cstdlib> #include <iostream> struct Empty {}; struct EmptyVirt { virtual ~EmptyVirt(){} }; struct NotEmpty { int m_i; }; struct NotEmptyVirt { virtual ~NotEmptyVirt() {} int m_i; }; struct NotEmptyNonVirt { void foo() const {} int m_i; }; int main() { std::cout << sizeof (Empty) << std::endl; std::cout << sizeof (EmptyVirt) << std::endl; std::cout << sizeof (NotEmpty) << std::endl; std::cout << sizeof (NotEmptyVirt) << std::endl; std::cout << sizeof (NotEmptyNonVirt) << std::endl; return EXIT_SUCCESS; } * This source code was highlighted with Source Code Highlighter .



  7. #include <cstdlib> #include <iostream> struct Empty {}; struct EmptyVirt { virtual ~EmptyVirt(){} }; struct NotEmpty { int m_i; }; struct NotEmptyVirt { virtual ~NotEmptyVirt() {} int m_i; }; struct NotEmptyNonVirt { void foo() const {} int m_i; }; int main() { std::cout << sizeof (Empty) << std::endl; std::cout << sizeof (EmptyVirt) << std::endl; std::cout << sizeof (NotEmpty) << std::endl; std::cout << sizeof (NotEmptyVirt) << std::endl; std::cout << sizeof (NotEmptyNonVirt) << std::endl; return EXIT_SUCCESS; } * This source code was highlighted with Source Code Highlighter .



  8. #include <cstdlib> #include <iostream> struct Empty {}; struct EmptyVirt { virtual ~EmptyVirt(){} }; struct NotEmpty { int m_i; }; struct NotEmptyVirt { virtual ~NotEmptyVirt() {} int m_i; }; struct NotEmptyNonVirt { void foo() const {} int m_i; }; int main() { std::cout << sizeof (Empty) << std::endl; std::cout << sizeof (EmptyVirt) << std::endl; std::cout << sizeof (NotEmpty) << std::endl; std::cout << sizeof (NotEmptyVirt) << std::endl; std::cout << sizeof (NotEmptyNonVirt) << std::endl; return EXIT_SUCCESS; } * This source code was highlighted with Source Code Highlighter .



  9. #include <cstdlib> #include <iostream> struct Empty {}; struct EmptyVirt { virtual ~EmptyVirt(){} }; struct NotEmpty { int m_i; }; struct NotEmptyVirt { virtual ~NotEmptyVirt() {} int m_i; }; struct NotEmptyNonVirt { void foo() const {} int m_i; }; int main() { std::cout << sizeof (Empty) << std::endl; std::cout << sizeof (EmptyVirt) << std::endl; std::cout << sizeof (NotEmpty) << std::endl; std::cout << sizeof (NotEmptyVirt) << std::endl; std::cout << sizeof (NotEmptyNonVirt) << std::endl; return EXIT_SUCCESS; } * This source code was highlighted with Source Code Highlighter .



  10. #include <cstdlib> #include <iostream> struct Empty {}; struct EmptyVirt { virtual ~EmptyVirt(){} }; struct NotEmpty { int m_i; }; struct NotEmptyVirt { virtual ~NotEmptyVirt() {} int m_i; }; struct NotEmptyNonVirt { void foo() const {} int m_i; }; int main() { std::cout << sizeof (Empty) << std::endl; std::cout << sizeof (EmptyVirt) << std::endl; std::cout << sizeof (NotEmpty) << std::endl; std::cout << sizeof (NotEmptyVirt) << std::endl; std::cout << sizeof (NotEmptyNonVirt) << std::endl; return EXIT_SUCCESS; } * This source code was highlighted with Source Code Highlighter .



  11. #include <cstdlib> #include <iostream> struct Empty {}; struct EmptyVirt { virtual ~EmptyVirt(){} }; struct NotEmpty { int m_i; }; struct NotEmptyVirt { virtual ~NotEmptyVirt() {} int m_i; }; struct NotEmptyNonVirt { void foo() const {} int m_i; }; int main() { std::cout << sizeof (Empty) << std::endl; std::cout << sizeof (EmptyVirt) << std::endl; std::cout << sizeof (NotEmpty) << std::endl; std::cout << sizeof (NotEmptyVirt) << std::endl; std::cout << sizeof (NotEmptyNonVirt) << std::endl; return EXIT_SUCCESS; } * This source code was highlighted with Source Code Highlighter .



  12. #include <cstdlib> #include <iostream> struct Empty {}; struct EmptyVirt { virtual ~EmptyVirt(){} }; struct NotEmpty { int m_i; }; struct NotEmptyVirt { virtual ~NotEmptyVirt() {} int m_i; }; struct NotEmptyNonVirt { void foo() const {} int m_i; }; int main() { std::cout << sizeof (Empty) << std::endl; std::cout << sizeof (EmptyVirt) << std::endl; std::cout << sizeof (NotEmpty) << std::endl; std::cout << sizeof (NotEmptyVirt) << std::endl; std::cout << sizeof (NotEmptyNonVirt) << std::endl; return EXIT_SUCCESS; } * This source code was highlighted with Source Code Highlighter .



  13. #include <cstdlib> #include <iostream> struct Empty {}; struct EmptyVirt { virtual ~EmptyVirt(){} }; struct NotEmpty { int m_i; }; struct NotEmptyVirt { virtual ~NotEmptyVirt() {} int m_i; }; struct NotEmptyNonVirt { void foo() const {} int m_i; }; int main() { std::cout << sizeof (Empty) << std::endl; std::cout << sizeof (EmptyVirt) << std::endl; std::cout << sizeof (NotEmpty) << std::endl; std::cout << sizeof (NotEmptyVirt) << std::endl; std::cout << sizeof (NotEmptyNonVirt) << std::endl; return EXIT_SUCCESS; } * This source code was highlighted with Source Code Highlighter .



  14. #include <cstdlib> #include <iostream> struct Empty {}; struct EmptyVirt { virtual ~EmptyVirt(){} }; struct NotEmpty { int m_i; }; struct NotEmptyVirt { virtual ~NotEmptyVirt() {} int m_i; }; struct NotEmptyNonVirt { void foo() const {} int m_i; }; int main() { std::cout << sizeof (Empty) << std::endl; std::cout << sizeof (EmptyVirt) << std::endl; std::cout << sizeof (NotEmpty) << std::endl; std::cout << sizeof (NotEmptyVirt) << std::endl; std::cout << sizeof (NotEmptyNonVirt) << std::endl; return EXIT_SUCCESS; } * This source code was highlighted with Source Code Highlighter .



  15. #include <cstdlib> #include <iostream> struct Empty {}; struct EmptyVirt { virtual ~EmptyVirt(){} }; struct NotEmpty { int m_i; }; struct NotEmptyVirt { virtual ~NotEmptyVirt() {} int m_i; }; struct NotEmptyNonVirt { void foo() const {} int m_i; }; int main() { std::cout << sizeof (Empty) << std::endl; std::cout << sizeof (EmptyVirt) << std::endl; std::cout << sizeof (NotEmpty) << std::endl; std::cout << sizeof (NotEmptyVirt) << std::endl; std::cout << sizeof (NotEmptyNonVirt) << std::endl; return EXIT_SUCCESS; } * This source code was highlighted with Source Code Highlighter .



  16. #include <cstdlib> #include <iostream> struct Empty {}; struct EmptyVirt { virtual ~EmptyVirt(){} }; struct NotEmpty { int m_i; }; struct NotEmptyVirt { virtual ~NotEmptyVirt() {} int m_i; }; struct NotEmptyNonVirt { void foo() const {} int m_i; }; int main() { std::cout << sizeof (Empty) << std::endl; std::cout << sizeof (EmptyVirt) << std::endl; std::cout << sizeof (NotEmpty) << std::endl; std::cout << sizeof (NotEmptyVirt) << std::endl; std::cout << sizeof (NotEmptyNonVirt) << std::endl; return EXIT_SUCCESS; } * This source code was highlighted with Source Code Highlighter .



  17. #include <cstdlib> #include <iostream> struct Empty {}; struct EmptyVirt { virtual ~EmptyVirt(){} }; struct NotEmpty { int m_i; }; struct NotEmptyVirt { virtual ~NotEmptyVirt() {} int m_i; }; struct NotEmptyNonVirt { void foo() const {} int m_i; }; int main() { std::cout << sizeof (Empty) << std::endl; std::cout << sizeof (EmptyVirt) << std::endl; std::cout << sizeof (NotEmpty) << std::endl; std::cout << sizeof (NotEmptyVirt) << std::endl; std::cout << sizeof (NotEmptyNonVirt) << std::endl; return EXIT_SUCCESS; } * This source code was highlighted with Source Code Highlighter .



  18. #include <cstdlib> #include <iostream> struct Empty {}; struct EmptyVirt { virtual ~EmptyVirt(){} }; struct NotEmpty { int m_i; }; struct NotEmptyVirt { virtual ~NotEmptyVirt() {} int m_i; }; struct NotEmptyNonVirt { void foo() const {} int m_i; }; int main() { std::cout << sizeof (Empty) << std::endl; std::cout << sizeof (EmptyVirt) << std::endl; std::cout << sizeof (NotEmpty) << std::endl; std::cout << sizeof (NotEmptyVirt) << std::endl; std::cout << sizeof (NotEmptyNonVirt) << std::endl; return EXIT_SUCCESS; } * This source code was highlighted with Source Code Highlighter .



  19. #include <cstdlib> #include <iostream> struct Empty {}; struct EmptyVirt { virtual ~EmptyVirt(){} }; struct NotEmpty { int m_i; }; struct NotEmptyVirt { virtual ~NotEmptyVirt() {} int m_i; }; struct NotEmptyNonVirt { void foo() const {} int m_i; }; int main() { std::cout << sizeof (Empty) << std::endl; std::cout << sizeof (EmptyVirt) << std::endl; std::cout << sizeof (NotEmpty) << std::endl; std::cout << sizeof (NotEmptyVirt) << std::endl; std::cout << sizeof (NotEmptyNonVirt) << std::endl; return EXIT_SUCCESS; } * This source code was highlighted with Source Code Highlighter .



  20. #include <cstdlib> #include <iostream> struct Empty {}; struct EmptyVirt { virtual ~EmptyVirt(){} }; struct NotEmpty { int m_i; }; struct NotEmptyVirt { virtual ~NotEmptyVirt() {} int m_i; }; struct NotEmptyNonVirt { void foo() const {} int m_i; }; int main() { std::cout << sizeof (Empty) << std::endl; std::cout << sizeof (EmptyVirt) << std::endl; std::cout << sizeof (NotEmpty) << std::endl; std::cout << sizeof (NotEmptyVirt) << std::endl; std::cout << sizeof (NotEmptyNonVirt) << std::endl; return EXIT_SUCCESS; } * This source code was highlighted with Source Code Highlighter .



  21. #include <cstdlib> #include <iostream> struct Empty {}; struct EmptyVirt { virtual ~EmptyVirt(){} }; struct NotEmpty { int m_i; }; struct NotEmptyVirt { virtual ~NotEmptyVirt() {} int m_i; }; struct NotEmptyNonVirt { void foo() const {} int m_i; }; int main() { std::cout << sizeof (Empty) << std::endl; std::cout << sizeof (EmptyVirt) << std::endl; std::cout << sizeof (NotEmpty) << std::endl; std::cout << sizeof (NotEmptyVirt) << std::endl; std::cout << sizeof (NotEmptyNonVirt) << std::endl; return EXIT_SUCCESS; } * This source code was highlighted with Source Code Highlighter .



  22. #include <cstdlib> #include <iostream> struct Empty {}; struct EmptyVirt { virtual ~EmptyVirt(){} }; struct NotEmpty { int m_i; }; struct NotEmptyVirt { virtual ~NotEmptyVirt() {} int m_i; }; struct NotEmptyNonVirt { void foo() const {} int m_i; }; int main() { std::cout << sizeof (Empty) << std::endl; std::cout << sizeof (EmptyVirt) << std::endl; std::cout << sizeof (NotEmpty) << std::endl; std::cout << sizeof (NotEmptyVirt) << std::endl; std::cout << sizeof (NotEmptyNonVirt) << std::endl; return EXIT_SUCCESS; } * This source code was highlighted with Source Code Highlighter .



  23. #include <cstdlib> #include <iostream> struct Empty {}; struct EmptyVirt { virtual ~EmptyVirt(){} }; struct NotEmpty { int m_i; }; struct NotEmptyVirt { virtual ~NotEmptyVirt() {} int m_i; }; struct NotEmptyNonVirt { void foo() const {} int m_i; }; int main() { std::cout << sizeof (Empty) << std::endl; std::cout << sizeof (EmptyVirt) << std::endl; std::cout << sizeof (NotEmpty) << std::endl; std::cout << sizeof (NotEmptyVirt) << std::endl; std::cout << sizeof (NotEmptyNonVirt) << std::endl; return EXIT_SUCCESS; } * This source code was highlighted with Source Code Highlighter .



  24. #include <cstdlib> #include <iostream> struct Empty {}; struct EmptyVirt { virtual ~EmptyVirt(){} }; struct NotEmpty { int m_i; }; struct NotEmptyVirt { virtual ~NotEmptyVirt() {} int m_i; }; struct NotEmptyNonVirt { void foo() const {} int m_i; }; int main() { std::cout << sizeof (Empty) << std::endl; std::cout << sizeof (EmptyVirt) << std::endl; std::cout << sizeof (NotEmpty) << std::endl; std::cout << sizeof (NotEmptyVirt) << std::endl; std::cout << sizeof (NotEmptyNonVirt) << std::endl; return EXIT_SUCCESS; } * This source code was highlighted with Source Code Highlighter .



#include <cstdlib> #include <iostream> struct Empty {}; struct EmptyVirt { virtual ~EmptyVirt(){} }; struct NotEmpty { int m_i; }; struct NotEmptyVirt { virtual ~NotEmptyVirt() {} int m_i; }; struct NotEmptyNonVirt { void foo() const {} int m_i; }; int main() { std::cout << sizeof (Empty) << std::endl; std::cout << sizeof (EmptyVirt) << std::endl; std::cout << sizeof (NotEmpty) << std::endl; std::cout << sizeof (NotEmptyVirt) << std::endl; std::cout << sizeof (NotEmptyNonVirt) << std::endl; return EXIT_SUCCESS; } * This source code was highlighted with Source Code Highlighter .







出力はプラットフォームによって異なる場合がありますが、私の場合(Win32、msvc2008)は次のとおりでした。



1

4

4

8

4




この例から理解できること。 まず、コンパイラがダミーのメンバーを特別に挿入するため、「空の」クラスのサイズは常にゼロより大きくなります。 Ekkelが書いているように、「ゼロサイズのオブジェクトの配列でインデックス作成プロセスを想像すると、すべてが明確になります」;)次に、仮想関数を追加するときの「空でない」クラスNotEmptyVirtのサイズは、voidへのポインターの標準サイズによって増加します。 また、「空の」クラスEmptyVirtでは、クラスをゼロ以外にするためにコンパイラーが以前に追加したダミーメンバーがポインターに置き換えられました。 同時に、クラスに非仮想関数を追加してもサイズに影響しません( tipのnullbieに感謝します )。 テーブルへのポインタの名前は、コンパイラによって異なります。 たとえば、 Visual Studio 2008コンパイラは__vfptrを呼び出し、テーブル自体は「vftable」です(デバッガーで見ることができると信じない人は誰でも)。文献では、仮想関数テーブルへのポインターはVPTRと呼ばれ、テーブル自体はVTABLEです。表記法。



仮想関数テーブルとは何ですか?なぜ必要なのですか? 仮想関数のテーブルには、クラスのすべての仮想メソッド(実際には、これはポインターの配列)のアドレスと、このクラスの基本クラスのすべての仮想メソッドが格納されます。



仮想関数を含むクラス(クラスごとに1つのテーブル)と同数の仮想関数テーブルがあります。 各クラスのオブジェクトには、テーブル自体ではなく、テーブルへのポインタが含まれています ! このテーマに関する質問は、教師やインタビューを行う人に尋ねるのが好きです。 (新規参入者を捕まえることができる難しい質問の例:「クラスに仮想関数のテーブルが含まれている場合、クラスオブジェクトのサイズはそれに含まれる仮想関数の数に依存しますか?」;「ベースクラスへのポインターの配列があり、それぞれのポイント派生クラスの1つのオブジェクト-いくつの仮想関数テーブルを持ちますか?」など)。



そのため、クラスごとに、仮想関数のテーブルを作成します。 基本クラスの各仮想関数には、連続したインデックスが(関数の宣言順に)割り当てられます。これにより、VTABLEテーブル内の関数本体のアドレスが決定されます。 基本クラスを継承すると、派生クラスは基本クラスの仮想関数のアドレスのテーブルと「取得」します。 派生クラスの仮想メソッドが再定義された場合、このクラスの仮想関数のテーブルでは、対応するメソッドの本体のアドレスが新しいものに単純に置き換えられます。 新しい仮想メソッドが派生クラスに追加されると、派生クラスのVTABLEが拡張され、基本クラステーブルは元のままになります。 したがって、基本クラスへのポインターを介して、基本クラスにない派生クラスのメソッドを仮想的に呼び出すことはできません。結局、基本クラスはそれらについて「何も知らない」ことになります(このすべてを例で説明します)。



クラスコンストラクターは、追加の操作を実行する必要があります。VPTRポインターを対応する仮想関数テーブルのアドレスで初期化します。 つまり、派生クラスのオブジェクトを作成すると、基本クラスのコンストラクターが最初に呼び出され、独自の仮想関数テーブルのアドレスでVPTRが初期化されます。次に、派生クラスのコンストラクターが呼び出され、この値が上書きされます。



基本クラスのアドレスを介して関数を呼び出す場合(読み取り-基本クラスへのポインターを介して)、コンパイラーはまずVPTRポインターを使用してクラスの仮想関数のテーブルを調べ、そこから呼び出された関数の本体のアドレスを取得する必要があります。



上記のことから、レイトバインディングメカニズムは、以前のものと比較して、追加のプロセッサ時間(VPTRコンストラクターの初期化、呼び出されたときに関数のアドレスの取得)が必要であると結論付けることができます。



例ですべてが明らかになると思います。 次の階層を考慮してください。







この場合、仮想関数の2つのテーブルを取得します。

ベース
0

ベース:: foo()
1 ベース::バー()
2 ベース:: baz()


そして

継承
0

ベース:: foo()
1 継承:: bar()
2 ベース:: baz()
3 継承:: qux()




ご覧のとおり、派生クラスの表では、2番目のメソッドのアドレスが、対応する再定義されたメソッドに置き換えられています。 証明コード:



#include <cstdlib> #include <iostream> using std::cout; using std::endl; struct Base { Base() { cout << "Base::Base()" << endl; } virtual ~Base() { cout << "Base::~Base()" << endl; } virtual void foo() { cout << "Base::foo()" << endl; } virtual void bar() { cout << "Base::bar()" << endl; } virtual void baz() { cout << "Base::baz()" << endl; } }; struct Inherited : public Base { Inherited() { cout << "Inherited::Inherited()" << endl; } virtual ~Inherited() { cout << "Inherited::~Inherited()" << endl; } virtual void bar() { cout << "Inherited::bar()" << endl; } virtual void qux() { cout << "Inherited::qux()" << endl; } }; int main() { Base * pBase = new Inherited; pBase->foo(); pBase->bar(); pBase->baz(); //pBase->qux(); // delete pBase; return EXIT_SUCCESS; } * This source code was highlighted with Source Code Highlighter .



  1. #include <cstdlib> #include <iostream> using std::cout; using std::endl; struct Base { Base() { cout << "Base::Base()" << endl; } virtual ~Base() { cout << "Base::~Base()" << endl; } virtual void foo() { cout << "Base::foo()" << endl; } virtual void bar() { cout << "Base::bar()" << endl; } virtual void baz() { cout << "Base::baz()" << endl; } }; struct Inherited : public Base { Inherited() { cout << "Inherited::Inherited()" << endl; } virtual ~Inherited() { cout << "Inherited::~Inherited()" << endl; } virtual void bar() { cout << "Inherited::bar()" << endl; } virtual void qux() { cout << "Inherited::qux()" << endl; } }; int main() { Base * pBase = new Inherited; pBase->foo(); pBase->bar(); pBase->baz(); //pBase->qux(); // delete pBase; return EXIT_SUCCESS; } * This source code was highlighted with Source Code Highlighter .



  2. #include <cstdlib> #include <iostream> using std::cout; using std::endl; struct Base { Base() { cout << "Base::Base()" << endl; } virtual ~Base() { cout << "Base::~Base()" << endl; } virtual void foo() { cout << "Base::foo()" << endl; } virtual void bar() { cout << "Base::bar()" << endl; } virtual void baz() { cout << "Base::baz()" << endl; } }; struct Inherited : public Base { Inherited() { cout << "Inherited::Inherited()" << endl; } virtual ~Inherited() { cout << "Inherited::~Inherited()" << endl; } virtual void bar() { cout << "Inherited::bar()" << endl; } virtual void qux() { cout << "Inherited::qux()" << endl; } }; int main() { Base * pBase = new Inherited; pBase->foo(); pBase->bar(); pBase->baz(); //pBase->qux(); // delete pBase; return EXIT_SUCCESS; } * This source code was highlighted with Source Code Highlighter .



  3. #include <cstdlib> #include <iostream> using std::cout; using std::endl; struct Base { Base() { cout << "Base::Base()" << endl; } virtual ~Base() { cout << "Base::~Base()" << endl; } virtual void foo() { cout << "Base::foo()" << endl; } virtual void bar() { cout << "Base::bar()" << endl; } virtual void baz() { cout << "Base::baz()" << endl; } }; struct Inherited : public Base { Inherited() { cout << "Inherited::Inherited()" << endl; } virtual ~Inherited() { cout << "Inherited::~Inherited()" << endl; } virtual void bar() { cout << "Inherited::bar()" << endl; } virtual void qux() { cout << "Inherited::qux()" << endl; } }; int main() { Base * pBase = new Inherited; pBase->foo(); pBase->bar(); pBase->baz(); //pBase->qux(); // delete pBase; return EXIT_SUCCESS; } * This source code was highlighted with Source Code Highlighter .



  4. #include <cstdlib> #include <iostream> using std::cout; using std::endl; struct Base { Base() { cout << "Base::Base()" << endl; } virtual ~Base() { cout << "Base::~Base()" << endl; } virtual void foo() { cout << "Base::foo()" << endl; } virtual void bar() { cout << "Base::bar()" << endl; } virtual void baz() { cout << "Base::baz()" << endl; } }; struct Inherited : public Base { Inherited() { cout << "Inherited::Inherited()" << endl; } virtual ~Inherited() { cout << "Inherited::~Inherited()" << endl; } virtual void bar() { cout << "Inherited::bar()" << endl; } virtual void qux() { cout << "Inherited::qux()" << endl; } }; int main() { Base * pBase = new Inherited; pBase->foo(); pBase->bar(); pBase->baz(); //pBase->qux(); // delete pBase; return EXIT_SUCCESS; } * This source code was highlighted with Source Code Highlighter .



  5. #include <cstdlib> #include <iostream> using std::cout; using std::endl; struct Base { Base() { cout << "Base::Base()" << endl; } virtual ~Base() { cout << "Base::~Base()" << endl; } virtual void foo() { cout << "Base::foo()" << endl; } virtual void bar() { cout << "Base::bar()" << endl; } virtual void baz() { cout << "Base::baz()" << endl; } }; struct Inherited : public Base { Inherited() { cout << "Inherited::Inherited()" << endl; } virtual ~Inherited() { cout << "Inherited::~Inherited()" << endl; } virtual void bar() { cout << "Inherited::bar()" << endl; } virtual void qux() { cout << "Inherited::qux()" << endl; } }; int main() { Base * pBase = new Inherited; pBase->foo(); pBase->bar(); pBase->baz(); //pBase->qux(); // delete pBase; return EXIT_SUCCESS; } * This source code was highlighted with Source Code Highlighter .



  6. #include <cstdlib> #include <iostream> using std::cout; using std::endl; struct Base { Base() { cout << "Base::Base()" << endl; } virtual ~Base() { cout << "Base::~Base()" << endl; } virtual void foo() { cout << "Base::foo()" << endl; } virtual void bar() { cout << "Base::bar()" << endl; } virtual void baz() { cout << "Base::baz()" << endl; } }; struct Inherited : public Base { Inherited() { cout << "Inherited::Inherited()" << endl; } virtual ~Inherited() { cout << "Inherited::~Inherited()" << endl; } virtual void bar() { cout << "Inherited::bar()" << endl; } virtual void qux() { cout << "Inherited::qux()" << endl; } }; int main() { Base * pBase = new Inherited; pBase->foo(); pBase->bar(); pBase->baz(); //pBase->qux(); // delete pBase; return EXIT_SUCCESS; } * This source code was highlighted with Source Code Highlighter .



  7. #include <cstdlib> #include <iostream> using std::cout; using std::endl; struct Base { Base() { cout << "Base::Base()" << endl; } virtual ~Base() { cout << "Base::~Base()" << endl; } virtual void foo() { cout << "Base::foo()" << endl; } virtual void bar() { cout << "Base::bar()" << endl; } virtual void baz() { cout << "Base::baz()" << endl; } }; struct Inherited : public Base { Inherited() { cout << "Inherited::Inherited()" << endl; } virtual ~Inherited() { cout << "Inherited::~Inherited()" << endl; } virtual void bar() { cout << "Inherited::bar()" << endl; } virtual void qux() { cout << "Inherited::qux()" << endl; } }; int main() { Base * pBase = new Inherited; pBase->foo(); pBase->bar(); pBase->baz(); //pBase->qux(); // delete pBase; return EXIT_SUCCESS; } * This source code was highlighted with Source Code Highlighter .



  8. #include <cstdlib> #include <iostream> using std::cout; using std::endl; struct Base { Base() { cout << "Base::Base()" << endl; } virtual ~Base() { cout << "Base::~Base()" << endl; } virtual void foo() { cout << "Base::foo()" << endl; } virtual void bar() { cout << "Base::bar()" << endl; } virtual void baz() { cout << "Base::baz()" << endl; } }; struct Inherited : public Base { Inherited() { cout << "Inherited::Inherited()" << endl; } virtual ~Inherited() { cout << "Inherited::~Inherited()" << endl; } virtual void bar() { cout << "Inherited::bar()" << endl; } virtual void qux() { cout << "Inherited::qux()" << endl; } }; int main() { Base * pBase = new Inherited; pBase->foo(); pBase->bar(); pBase->baz(); //pBase->qux(); // delete pBase; return EXIT_SUCCESS; } * This source code was highlighted with Source Code Highlighter .



  9. #include <cstdlib> #include <iostream> using std::cout; using std::endl; struct Base { Base() { cout << "Base::Base()" << endl; } virtual ~Base() { cout << "Base::~Base()" << endl; } virtual void foo() { cout << "Base::foo()" << endl; } virtual void bar() { cout << "Base::bar()" << endl; } virtual void baz() { cout << "Base::baz()" << endl; } }; struct Inherited : public Base { Inherited() { cout << "Inherited::Inherited()" << endl; } virtual ~Inherited() { cout << "Inherited::~Inherited()" << endl; } virtual void bar() { cout << "Inherited::bar()" << endl; } virtual void qux() { cout << "Inherited::qux()" << endl; } }; int main() { Base * pBase = new Inherited; pBase->foo(); pBase->bar(); pBase->baz(); //pBase->qux(); // delete pBase; return EXIT_SUCCESS; } * This source code was highlighted with Source Code Highlighter .



  10. #include <cstdlib> #include <iostream> using std::cout; using std::endl; struct Base { Base() { cout << "Base::Base()" << endl; } virtual ~Base() { cout << "Base::~Base()" << endl; } virtual void foo() { cout << "Base::foo()" << endl; } virtual void bar() { cout << "Base::bar()" << endl; } virtual void baz() { cout << "Base::baz()" << endl; } }; struct Inherited : public Base { Inherited() { cout << "Inherited::Inherited()" << endl; } virtual ~Inherited() { cout << "Inherited::~Inherited()" << endl; } virtual void bar() { cout << "Inherited::bar()" << endl; } virtual void qux() { cout << "Inherited::qux()" << endl; } }; int main() { Base * pBase = new Inherited; pBase->foo(); pBase->bar(); pBase->baz(); //pBase->qux(); // delete pBase; return EXIT_SUCCESS; } * This source code was highlighted with Source Code Highlighter .



  11. #include <cstdlib> #include <iostream> using std::cout; using std::endl; struct Base { Base() { cout << "Base::Base()" << endl; } virtual ~Base() { cout << "Base::~Base()" << endl; } virtual void foo() { cout << "Base::foo()" << endl; } virtual void bar() { cout << "Base::bar()" << endl; } virtual void baz() { cout << "Base::baz()" << endl; } }; struct Inherited : public Base { Inherited() { cout << "Inherited::Inherited()" << endl; } virtual ~Inherited() { cout << "Inherited::~Inherited()" << endl; } virtual void bar() { cout << "Inherited::bar()" << endl; } virtual void qux() { cout << "Inherited::qux()" << endl; } }; int main() { Base * pBase = new Inherited; pBase->foo(); pBase->bar(); pBase->baz(); //pBase->qux(); // delete pBase; return EXIT_SUCCESS; } * This source code was highlighted with Source Code Highlighter .



  12. #include <cstdlib> #include <iostream> using std::cout; using std::endl; struct Base { Base() { cout << "Base::Base()" << endl; } virtual ~Base() { cout << "Base::~Base()" << endl; } virtual void foo() { cout << "Base::foo()" << endl; } virtual void bar() { cout << "Base::bar()" << endl; } virtual void baz() { cout << "Base::baz()" << endl; } }; struct Inherited : public Base { Inherited() { cout << "Inherited::Inherited()" << endl; } virtual ~Inherited() { cout << "Inherited::~Inherited()" << endl; } virtual void bar() { cout << "Inherited::bar()" << endl; } virtual void qux() { cout << "Inherited::qux()" << endl; } }; int main() { Base * pBase = new Inherited; pBase->foo(); pBase->bar(); pBase->baz(); //pBase->qux(); // delete pBase; return EXIT_SUCCESS; } * This source code was highlighted with Source Code Highlighter .



  13. #include <cstdlib> #include <iostream> using std::cout; using std::endl; struct Base { Base() { cout << "Base::Base()" << endl; } virtual ~Base() { cout << "Base::~Base()" << endl; } virtual void foo() { cout << "Base::foo()" << endl; } virtual void bar() { cout << "Base::bar()" << endl; } virtual void baz() { cout << "Base::baz()" << endl; } }; struct Inherited : public Base { Inherited() { cout << "Inherited::Inherited()" << endl; } virtual ~Inherited() { cout << "Inherited::~Inherited()" << endl; } virtual void bar() { cout << "Inherited::bar()" << endl; } virtual void qux() { cout << "Inherited::qux()" << endl; } }; int main() { Base * pBase = new Inherited; pBase->foo(); pBase->bar(); pBase->baz(); //pBase->qux(); // delete pBase; return EXIT_SUCCESS; } * This source code was highlighted with Source Code Highlighter .



  14. #include <cstdlib> #include <iostream> using std::cout; using std::endl; struct Base { Base() { cout << "Base::Base()" << endl; } virtual ~Base() { cout << "Base::~Base()" << endl; } virtual void foo() { cout << "Base::foo()" << endl; } virtual void bar() { cout << "Base::bar()" << endl; } virtual void baz() { cout << "Base::baz()" << endl; } }; struct Inherited : public Base { Inherited() { cout << "Inherited::Inherited()" << endl; } virtual ~Inherited() { cout << "Inherited::~Inherited()" << endl; } virtual void bar() { cout << "Inherited::bar()" << endl; } virtual void qux() { cout << "Inherited::qux()" << endl; } }; int main() { Base * pBase = new Inherited; pBase->foo(); pBase->bar(); pBase->baz(); //pBase->qux(); // delete pBase; return EXIT_SUCCESS; } * This source code was highlighted with Source Code Highlighter .



  15. #include <cstdlib> #include <iostream> using std::cout; using std::endl; struct Base { Base() { cout << "Base::Base()" << endl; } virtual ~Base() { cout << "Base::~Base()" << endl; } virtual void foo() { cout << "Base::foo()" << endl; } virtual void bar() { cout << "Base::bar()" << endl; } virtual void baz() { cout << "Base::baz()" << endl; } }; struct Inherited : public Base { Inherited() { cout << "Inherited::Inherited()" << endl; } virtual ~Inherited() { cout << "Inherited::~Inherited()" << endl; } virtual void bar() { cout << "Inherited::bar()" << endl; } virtual void qux() { cout << "Inherited::qux()" << endl; } }; int main() { Base * pBase = new Inherited; pBase->foo(); pBase->bar(); pBase->baz(); //pBase->qux(); // delete pBase; return EXIT_SUCCESS; } * This source code was highlighted with Source Code Highlighter .



  16. #include <cstdlib> #include <iostream> using std::cout; using std::endl; struct Base { Base() { cout << "Base::Base()" << endl; } virtual ~Base() { cout << "Base::~Base()" << endl; } virtual void foo() { cout << "Base::foo()" << endl; } virtual void bar() { cout << "Base::bar()" << endl; } virtual void baz() { cout << "Base::baz()" << endl; } }; struct Inherited : public Base { Inherited() { cout << "Inherited::Inherited()" << endl; } virtual ~Inherited() { cout << "Inherited::~Inherited()" << endl; } virtual void bar() { cout << "Inherited::bar()" << endl; } virtual void qux() { cout << "Inherited::qux()" << endl; } }; int main() { Base * pBase = new Inherited; pBase->foo(); pBase->bar(); pBase->baz(); //pBase->qux(); // delete pBase; return EXIT_SUCCESS; } * This source code was highlighted with Source Code Highlighter .



  17. #include <cstdlib> #include <iostream> using std::cout; using std::endl; struct Base { Base() { cout << "Base::Base()" << endl; } virtual ~Base() { cout << "Base::~Base()" << endl; } virtual void foo() { cout << "Base::foo()" << endl; } virtual void bar() { cout << "Base::bar()" << endl; } virtual void baz() { cout << "Base::baz()" << endl; } }; struct Inherited : public Base { Inherited() { cout << "Inherited::Inherited()" << endl; } virtual ~Inherited() { cout << "Inherited::~Inherited()" << endl; } virtual void bar() { cout << "Inherited::bar()" << endl; } virtual void qux() { cout << "Inherited::qux()" << endl; } }; int main() { Base * pBase = new Inherited; pBase->foo(); pBase->bar(); pBase->baz(); //pBase->qux(); // delete pBase; return EXIT_SUCCESS; } * This source code was highlighted with Source Code Highlighter .



  18. #include <cstdlib> #include <iostream> using std::cout; using std::endl; struct Base { Base() { cout << "Base::Base()" << endl; } virtual ~Base() { cout << "Base::~Base()" << endl; } virtual void foo() { cout << "Base::foo()" << endl; } virtual void bar() { cout << "Base::bar()" << endl; } virtual void baz() { cout << "Base::baz()" << endl; } }; struct Inherited : public Base { Inherited() { cout << "Inherited::Inherited()" << endl; } virtual ~Inherited() { cout << "Inherited::~Inherited()" << endl; } virtual void bar() { cout << "Inherited::bar()" << endl; } virtual void qux() { cout << "Inherited::qux()" << endl; } }; int main() { Base * pBase = new Inherited; pBase->foo(); pBase->bar(); pBase->baz(); //pBase->qux(); // delete pBase; return EXIT_SUCCESS; } * This source code was highlighted with Source Code Highlighter .



  19. #include <cstdlib> #include <iostream> using std::cout; using std::endl; struct Base { Base() { cout << "Base::Base()" << endl; } virtual ~Base() { cout << "Base::~Base()" << endl; } virtual void foo() { cout << "Base::foo()" << endl; } virtual void bar() { cout << "Base::bar()" << endl; } virtual void baz() { cout << "Base::baz()" << endl; } }; struct Inherited : public Base { Inherited() { cout << "Inherited::Inherited()" << endl; } virtual ~Inherited() { cout << "Inherited::~Inherited()" << endl; } virtual void bar() { cout << "Inherited::bar()" << endl; } virtual void qux() { cout << "Inherited::qux()" << endl; } }; int main() { Base * pBase = new Inherited; pBase->foo(); pBase->bar(); pBase->baz(); //pBase->qux(); // delete pBase; return EXIT_SUCCESS; } * This source code was highlighted with Source Code Highlighter .



  20. #include <cstdlib> #include <iostream> using std::cout; using std::endl; struct Base { Base() { cout << "Base::Base()" << endl; } virtual ~Base() { cout << "Base::~Base()" << endl; } virtual void foo() { cout << "Base::foo()" << endl; } virtual void bar() { cout << "Base::bar()" << endl; } virtual void baz() { cout << "Base::baz()" << endl; } }; struct Inherited : public Base { Inherited() { cout << "Inherited::Inherited()" << endl; } virtual ~Inherited() { cout << "Inherited::~Inherited()" << endl; } virtual void bar() { cout << "Inherited::bar()" << endl; } virtual void qux() { cout << "Inherited::qux()" << endl; } }; int main() { Base * pBase = new Inherited; pBase->foo(); pBase->bar(); pBase->baz(); //pBase->qux(); // delete pBase; return EXIT_SUCCESS; } * This source code was highlighted with Source Code Highlighter .



  21. #include <cstdlib> #include <iostream> using std::cout; using std::endl; struct Base { Base() { cout << "Base::Base()" << endl; } virtual ~Base() { cout << "Base::~Base()" << endl; } virtual void foo() { cout << "Base::foo()" << endl; } virtual void bar() { cout << "Base::bar()" << endl; } virtual void baz() { cout << "Base::baz()" << endl; } }; struct Inherited : public Base { Inherited() { cout << "Inherited::Inherited()" << endl; } virtual ~Inherited() { cout << "Inherited::~Inherited()" << endl; } virtual void bar() { cout << "Inherited::bar()" << endl; } virtual void qux() { cout << "Inherited::qux()" << endl; } }; int main() { Base * pBase = new Inherited; pBase->foo(); pBase->bar(); pBase->baz(); //pBase->qux(); // delete pBase; return EXIT_SUCCESS; } * This source code was highlighted with Source Code Highlighter .



  22. #include <cstdlib> #include <iostream> using std::cout; using std::endl; struct Base { Base() { cout << "Base::Base()" << endl; } virtual ~Base() { cout << "Base::~Base()" << endl; } virtual void foo() { cout << "Base::foo()" << endl; } virtual void bar() { cout << "Base::bar()" << endl; } virtual void baz() { cout << "Base::baz()" << endl; } }; struct Inherited : public Base { Inherited() { cout << "Inherited::Inherited()" << endl; } virtual ~Inherited() { cout << "Inherited::~Inherited()" << endl; } virtual void bar() { cout << "Inherited::bar()" << endl; } virtual void qux() { cout << "Inherited::qux()" << endl; } }; int main() { Base * pBase = new Inherited; pBase->foo(); pBase->bar(); pBase->baz(); //pBase->qux(); // delete pBase; return EXIT_SUCCESS; } * This source code was highlighted with Source Code Highlighter .



  23. #include <cstdlib> #include <iostream> using std::cout; using std::endl; struct Base { Base() { cout << "Base::Base()" << endl; } virtual ~Base() { cout << "Base::~Base()" << endl; } virtual void foo() { cout << "Base::foo()" << endl; } virtual void bar() { cout << "Base::bar()" << endl; } virtual void baz() { cout << "Base::baz()" << endl; } }; struct Inherited : public Base { Inherited() { cout << "Inherited::Inherited()" << endl; } virtual ~Inherited() { cout << "Inherited::~Inherited()" << endl; } virtual void bar() { cout << "Inherited::bar()" << endl; } virtual void qux() { cout << "Inherited::qux()" << endl; } }; int main() { Base * pBase = new Inherited; pBase->foo(); pBase->bar(); pBase->baz(); //pBase->qux(); // delete pBase; return EXIT_SUCCESS; } * This source code was highlighted with Source Code Highlighter .



  24. #include <cstdlib> #include <iostream> using std::cout; using std::endl; struct Base { Base() { cout << "Base::Base()" << endl; } virtual ~Base() { cout << "Base::~Base()" << endl; } virtual void foo() { cout << "Base::foo()" << endl; } virtual void bar() { cout << "Base::bar()" << endl; } virtual void baz() { cout << "Base::baz()" << endl; } }; struct Inherited : public Base { Inherited() { cout << "Inherited::Inherited()" << endl; } virtual ~Inherited() { cout << "Inherited::~Inherited()" << endl; } virtual void bar() { cout << "Inherited::bar()" << endl; } virtual void qux() { cout << "Inherited::qux()" << endl; } }; int main() { Base * pBase = new Inherited; pBase->foo(); pBase->bar(); pBase->baz(); //pBase->qux(); // delete pBase; return EXIT_SUCCESS; } * This source code was highlighted with Source Code Highlighter .



  25. #include <cstdlib> #include <iostream> using std::cout; using std::endl; struct Base { Base() { cout << "Base::Base()" << endl; } virtual ~Base() { cout << "Base::~Base()" << endl; } virtual void foo() { cout << "Base::foo()" << endl; } virtual void bar() { cout << "Base::bar()" << endl; } virtual void baz() { cout << "Base::baz()" << endl; } }; struct Inherited : public Base { Inherited() { cout << "Inherited::Inherited()" << endl; } virtual ~Inherited() { cout << "Inherited::~Inherited()" << endl; } virtual void bar() { cout << "Inherited::bar()" << endl; } virtual void qux() { cout << "Inherited::qux()" << endl; } }; int main() { Base * pBase = new Inherited; pBase->foo(); pBase->bar(); pBase->baz(); //pBase->qux(); // delete pBase; return EXIT_SUCCESS; } * This source code was highlighted with Source Code Highlighter .



  26. #include <cstdlib> #include <iostream> using std::cout; using std::endl; struct Base { Base() { cout << "Base::Base()" << endl; } virtual ~Base() { cout << "Base::~Base()" << endl; } virtual void foo() { cout << "Base::foo()" << endl; } virtual void bar() { cout << "Base::bar()" << endl; } virtual void baz() { cout << "Base::baz()" << endl; } }; struct Inherited : public Base { Inherited() { cout << "Inherited::Inherited()" << endl; } virtual ~Inherited() { cout << "Inherited::~Inherited()" << endl; } virtual void bar() { cout << "Inherited::bar()" << endl; } virtual void qux() { cout << "Inherited::qux()" << endl; } }; int main() { Base * pBase = new Inherited; pBase->foo(); pBase->bar(); pBase->baz(); //pBase->qux(); // delete pBase; return EXIT_SUCCESS; } * This source code was highlighted with Source Code Highlighter .



  27. #include <cstdlib> #include <iostream> using std::cout; using std::endl; struct Base { Base() { cout << "Base::Base()" << endl; } virtual ~Base() { cout << "Base::~Base()" << endl; } virtual void foo() { cout << "Base::foo()" << endl; } virtual void bar() { cout << "Base::bar()" << endl; } virtual void baz() { cout << "Base::baz()" << endl; } }; struct Inherited : public Base { Inherited() { cout << "Inherited::Inherited()" << endl; } virtual ~Inherited() { cout << "Inherited::~Inherited()" << endl; } virtual void bar() { cout << "Inherited::bar()" << endl; } virtual void qux() { cout << "Inherited::qux()" << endl; } }; int main() { Base * pBase = new Inherited; pBase->foo(); pBase->bar(); pBase->baz(); //pBase->qux(); // delete pBase; return EXIT_SUCCESS; } * This source code was highlighted with Source Code Highlighter .



  28. #include <cstdlib> #include <iostream> using std::cout; using std::endl; struct Base { Base() { cout << "Base::Base()" << endl; } virtual ~Base() { cout << "Base::~Base()" << endl; } virtual void foo() { cout << "Base::foo()" << endl; } virtual void bar() { cout << "Base::bar()" << endl; } virtual void baz() { cout << "Base::baz()" << endl; } }; struct Inherited : public Base { Inherited() { cout << "Inherited::Inherited()" << endl; } virtual ~Inherited() { cout << "Inherited::~Inherited()" << endl; } virtual void bar() { cout << "Inherited::bar()" << endl; } virtual void qux() { cout << "Inherited::qux()" << endl; } }; int main() { Base * pBase = new Inherited; pBase->foo(); pBase->bar(); pBase->baz(); //pBase->qux(); // delete pBase; return EXIT_SUCCESS; } * This source code was highlighted with Source Code Highlighter .



  29. #include <cstdlib> #include <iostream> using std::cout; using std::endl; struct Base { Base() { cout << "Base::Base()" << endl; } virtual ~Base() { cout << "Base::~Base()" << endl; } virtual void foo() { cout << "Base::foo()" << endl; } virtual void bar() { cout << "Base::bar()" << endl; } virtual void baz() { cout << "Base::baz()" << endl; } }; struct Inherited : public Base { Inherited() { cout << "Inherited::Inherited()" << endl; } virtual ~Inherited() { cout << "Inherited::~Inherited()" << endl; } virtual void bar() { cout << "Inherited::bar()" << endl; } virtual void qux() { cout << "Inherited::qux()" << endl; } }; int main() { Base * pBase = new Inherited; pBase->foo(); pBase->bar(); pBase->baz(); //pBase->qux(); // delete pBase; return EXIT_SUCCESS; } * This source code was highlighted with Source Code Highlighter .



#include <cstdlib> #include <iostream> using std::cout; using std::endl; struct Base { Base() { cout << "Base::Base()" << endl; } virtual ~Base() { cout << "Base::~Base()" << endl; } virtual void foo() { cout << "Base::foo()" << endl; } virtual void bar() { cout << "Base::bar()" << endl; } virtual void baz() { cout << "Base::baz()" << endl; } }; struct Inherited : public Base { Inherited() { cout << "Inherited::Inherited()" << endl; } virtual ~Inherited() { cout << "Inherited::~Inherited()" << endl; } virtual void bar() { cout << "Inherited::bar()" << endl; } virtual void qux() { cout << "Inherited::qux()" << endl; } }; int main() { Base * pBase = new Inherited; pBase->foo(); pBase->bar(); pBase->baz(); //pBase->qux(); // delete pBase; return EXIT_SUCCESS; } * This source code was highlighted with Source Code Highlighter .







プログラムが起動するとどうなりますか? 最初に、Base型のオブジェクトへのポインターを宣言します。この型に、新しく作成されたInherited型のオブジェクトのアドレスを割り当てます。 この場合、Baseコンストラクターが呼び出され、BaseクラスのVTABLEアドレスでVPTRが初期化され、次にInheritedクラスのVTABLEアドレスでVPTR値を上書きするInheritedコンストラクターが初期化されます。 pBase-> foo()pBase-> bar()およびpBase-> baz()が呼び出されると、コンパイラは、VPTRポインターを介して、仮想関数テーブルから関数本体の実際のアドレスを取得します。 これはどうですか? オブジェクトの特定のタイプに関係なく、コンパイラーは関数foo()のアドレスが最初にあり、 bar()が2番目にあることを知っています。 (私が言ったように、関数の宣言の順に)。 したがって、たとえば、 baz()関数を呼び出すには、VPTR + 2の形式で関数のアドレス(仮想関数テーブルの先頭からのオフセットを受け取り、このアドレスを保存してcallコマンドに代入します。 同じ理由で、 pBase-> qux()を呼び出すとエラーが発生します。継承オブジェクトの実際の型が、そのアドレスをBaseへのポインターに割り当てると、上方型変換が行われ、BaseクラスVTABLEテーブルには4番目のメソッドがありません、したがってVPTR + 3は他の誰かのメモリを指します(残念なことに、そのようなコードはコンパイルさえしません)。



神話に戻ります。 仮想関数の実装に対するこのアプローチでは、階層の1つのレベルでのみ関数を仮想化することは不可能であることが明らかになります。



また、仮想関数がオブジェクトのアドレスにアクセスする場合にのみ機能する理由も明らかになります(ポインターまたはリンクを介して)。 私が言ったように、この行で

Base * pBase = new Inherited;





インクリメンタルキャストがあります。継承された*はベース*にキャストされますが、いずれの場合も、ポインターはオブジェクトの「開始」のアドレスのみをメモリに格納します。 オブジェクトに対してキャストが直接実行される場合、実際には基本クラスオブジェクトのサイズに「クリップ」されます。 したがって、「オブジェクトを介して」関数を呼び出すために早期呼び出しが使用されるのは論理的です。コンパイラはオブジェクトの実際の型をすでに「知っています」。



実際、それだけです。 コメントを待っています。 ご清聴ありがとうございました。



PSこの記事には「Warranty of Speed」というラベルが付けられています©

(Skor、これを読んだら、これはあなたのためです;)



PPSはい、私は言い忘れました... Javistsは、Javaではデフォルトですべての機能が仮想であると叫び始めます。

_________

テキストはHabraで準備されます



プログイット



All Articles