C++学習ノート27、虚関数作品
2251 ワード
C++は虚関数の動作を指定するが、実現した著者コンパイラである.
通常、コンパイラが虚関数を処理する方法は、各オブジェクトに非表示のメンバーを加えることである.非表示のメンバーには、関数のアドレス配列を指すポインタが保存されます.
この配列を虚関数テーブル(virtual function table,vtbl)と呼ぶ.ダミー関数テーブルには、クラスオブジェクトを宣言するダミー関数のアドレスが格納.
例えば、ベースクラスオブジェクトは、ベースクラスの虚関数テーブルを指すポインタを含む.
派生クラスオブジェクトは、独立した虚関数テーブルを指すポインタを含む.派生クラスが虚関数の新しい定義を提供すると仮定し、虚関数テーブルは新しい関数アドレスを保存する.
派生クラスが再び虚関数を定義していないと仮定すると、虚関数テーブルには元の番号のアドレスが保存される.派生クラスが新しい虚関数を定義したと仮定すると、その関数アドレスも虚関数数テーブルに追加されます.
以下の例を見てください.
注意eatは虚関数ではなく、虚関数テーブルに保存されません.
///Animalダミーテーブルアドレス:1000
Animal::run() 4000
Animal::speak()5000 Dogダミー関数テーブルアドレス:2000
Dog::run()4000(書き換えられず、元のアドレスを保存)
Dog::speak()7000(書き換え、新しいアドレスを保存)
Dog::fun()8000(新しい虚関数、保存アドレス)
以下のコードp 1->speak();//を具体的に分析するAnimalのspeakのアドレスを見つけて、5000 p 2->speak();//Dogの中のspeakのアドレスを見つけて、7000、コードDogを実行します::speak();p1->run(); //同上p 2->run();//このように、虚関数テーブルに対して初歩的な認識があります!
本文のブログのオリジナルの文章.ブログは、同意を得ずに転載してはならない.
通常、コンパイラが虚関数を処理する方法は、各オブジェクトに非表示のメンバーを加えることである.非表示のメンバーには、関数のアドレス配列を指すポインタが保存されます.
この配列を虚関数テーブル(virtual function table,vtbl)と呼ぶ.ダミー関数テーブルには、クラスオブジェクトを宣言するダミー関数のアドレスが格納.
例えば、ベースクラスオブジェクトは、ベースクラスの虚関数テーブルを指すポインタを含む.
派生クラスオブジェクトは、独立した虚関数テーブルを指すポインタを含む.派生クラスが虚関数の新しい定義を提供すると仮定し、虚関数テーブルは新しい関数アドレスを保存する.
派生クラスが再び虚関数を定義していないと仮定すると、虚関数テーブルには元の番号のアドレスが保存される.派生クラスが新しい虚関数を定義したと仮定すると、その関数アドレスも虚関数数テーブルに追加されます.
以下の例を見てください.
#include <iostream>
#include <string>
using namespace std;
class Animal{
protected:
string name;
public:
Animal(const string &s):name(s){
}
virtual ~Animal(){
}
//
void eat()const{
cout<<"Animal eat!"<<endl;
}
//
virtual void run()const{
cout<<"Animal run!"<<endl;
}
//
virtual void speak()const{
cout<<"I'm a Animal!"<<endl;
}
};
class Dog:public Animal{
public:
Dog(const string &s):Animal(s){
}
virtual ~Dog(){
}
// eat, , ( virtual )
void eat()const{
cout<<"Dog eat!"<<endl;
}
// speak()
virtual void speak()const override{
cout<<"This's a Dog!"<<endl;
}
//
virtual void fun1()const{
}
};
int main(){
Animal a("AnimalOne");
Dog d1("DogOne");
Animal *p1=&a;
Animal *p2=&d1;
p1->speak();
p2->speak();
p1->eat();
p2->eat(); //call Animal::eat()
p1->run();
p2->run(); //call Animal::run()
Animal &r1=a;
Animal &r2=d1;
r1.speak();
r2.speak();
r1.eat();
r2.eat();
r1.run();
r2.run();
return 0;
}
注意eatは虚関数ではなく、虚関数テーブルに保存されません.
///Animalダミーテーブルアドレス:1000
Animal::run() 4000
Animal::speak()5000 Dogダミー関数テーブルアドレス:2000
Dog::run()4000(書き換えられず、元のアドレスを保存)
Dog::speak()7000(書き換え、新しいアドレスを保存)
Dog::fun()8000(新しい虚関数、保存アドレス)
以下のコードp 1->speak();//を具体的に分析するAnimalのspeakのアドレスを見つけて、5000 p 2->speak();//Dogの中のspeakのアドレスを見つけて、7000、コードDogを実行します::speak();p1->run(); //同上p 2->run();//このように、虚関数テーブルに対して初歩的な認識があります!
本文のブログのオリジナルの文章.ブログは、同意を得ずに転載してはならない.