私が継承について最初に知ったとき、私の先生は、データメンバーとは対照的に、メンバー関数はクラスのサイズを変更しないと述べました。つまり、クラスBがクラスAから継承する場合、少なくとも1つのデータメンバーが追加される場合に限り、BのサイズはAのサイズよりも大きくなり、関数メンバーの数に関して変更されません。それが正しいか?もしそうなら、このメカニズムはどのように機能しますか?両方のメンバーをヒープに保持する必要があるため、サイズが高くなるようです。
ありがとう、ガイ
私が継承について最初に知ったとき、私の先生は、データメンバーとは対照的に、メンバー関数はクラスのサイズを変更しないと述べました。つまり、クラスBがクラスAから継承する場合、少なくとも1つのデータメンバーが追加される場合に限り、BのサイズはAのサイズよりも大きくなり、関数メンバーの数に関して変更されません。それが正しいか?もしそうなら、このメカニズムはどのように機能しますか?両方のメンバーをヒープに保持する必要があるため、サイズが高くなるようです。
ありがとう、ガイ
メンバー変数は、各クラスインスタンスの一部として格納されます。しかし、メンバー関数はそうではありません。
クラスの各インスタンスには、各メンバー変数の個別のコピーが必要です。これにより、各オブジェクトが一意に保たれます。
しかし、メンバー関数はコードです。また、特定のクラスのインスタンスがいくつあっても、コードの複数のコピーを作成する理由はまったくありません。同じコードがインスタンスデータを操作するだけです。
コードが異なるため、コードはクラスインスタンスのサイズの一部ではありません。またsizeof(myClass)
、コードが占めるバイトは含まれません。
myClass.myMethod(x)
メンバー関数の呼び出しはに似ていると想像できますmyMethod(myClass, x)
。その関数がクラスのすべてのインスタンスごとに存在する必要はありません。this
キーワードを使用して、この「非表示」の最初の引数にアクセスできます。
クラスBがクラスAを継承する場合、少なくとも1つのデータメンバーが追加され、関数メンバーの数に関して変更されない場合に限り、BのサイズはAのサイズよりも大きくなります。
はい、それは正しいです。(Bが他のメソッドを実装していない場合)。各クラスインスタンスには、データメンバーのコピーと、それらが実際に格納されているメンバー関数テーブルへのポインタがあります。
メンバー関数のコードは、同じクラスの異なるインスタンス間で共有されます。Bが基本クラスAのメンバー関数をオーバーライドしない場合、AとBの両方が同じメソッドを共有できます。サブクラスのメンバー関数をオーバーライドすると、基本的にこのメカニズムが変更され、オーバーライドされたメンバー関数の新しい定義が作成されます。これは、定義したサブクラス(es.B)でのみ使用できます。
通常、メンバー関数はコンパイル時にバインドされます。したがって、基本クラスAへのポインターを介して参照されるサブクラスBのインスタンスがあり、両方のクラスで定義されたメンバー関数foo()を呼び出す場合、呼び出される関数は基本クラスに実装されたものになります。実行時にメンバー関数を強制的にバインドして仮想として宣言することができます(呼び出されるメンバー関数は、ベースポインターを指すクラスの実際の型の1つになります)。これにより、仮想メソッドを格納するために追加のテーブル(仮想メソッドテーブル、vtable)が使用され、呼び出しごとにダブルポインターの間接参照が行われます。