ssacontents/c++lesson-chap2
をテンプレートにして作成
Check
[
トップ
] [
新規
|
一覧
|
単語検索
|
最終更新
|
ヘルプ
]
開始行:
*親クラスの非仮想デストラクタについて [#fb64cc10]
**基底クラスのデストラクタを仮想(virtual)にする理由 [#fd7...
-C++の入門書には、必ず「基底クラスのデストラクタはvirtual...
-理由は、サブクラスのオブジェクトを基底クラスのポインタと...
非仮想な基底クラス
class Super {
public:
Super(){}
~Super(){} // virtualでない
};
// サブクラス
class Sub : public Super {
public:
Sub()
: m_sub(new int[10])
{}
~Sub() {
delete [] m_sub;
}
private:
int* m_sub;
};
Super* super = new Sub; // 基底クラスのポインタとしてsub...
...
delete super; // Superのデストラクタは仮想ではないため、
// Subのデストラクタは呼ばれない。(コンパ...
// superが実はSubのポインタだということを...
// べがない)
Sub::m_subがメモリリークする!
もしSuperのデストラクタが仮想の場合、
Super* super = new Sub; // 基底クラスのポインタとしてsub...
// superには仮想関数を処理するた...
// v-tableという領域(の*)が付加...
...
delete super; // Superのデストラクタは仮想なので、v-tabl...
// 参照し、Subのデストラクタが呼ばれた後に
// Superのデストラクタが呼ばれる。したがっ...
// メモリリークは発生しない。
**仮想デストラクタがあると何が起こるか? [#mb28f764]
C++のメモリ管理と仮想関数の仕組み
(+文字はコンパイラによって自動的に追加されるコード)
// クラス定義
class Super {
+ struct _vtable_t {
+ void (*destructor)();
+ }
+ static _vtable_t _vtable = { &~Super };
+ _vtable_t* _p_vtable;};
public:
Super(){}
virtual ~Super(){}
private:
int m_super;
};
// サブクラス
class Sub : public Super {
+ static _vtable_t _vtable = { &~Sub };
public:
Sub() : m_sub(new int[10]) {}
~Sub() { delete [] m_sub; }
private:
int* m_sub;
};
newとdelete時の動作
Super* super = new Sub;
+ super = (Super*)malloc(sizeof(Sub));
+ super->_p_vtable = &Sub::_vtable;
+ Sub::Sub(super); // コンストラクタを呼び出す
.....
delete super;
+ super->_p_vtable->destructor(); // Sub::~Sub()が呼ばれる
+ free((void*)super); // メモリ管理システムにより、malloc
// したときのメモリブロックが解放...
- メモリリークを回避するため、すべての基底クラスは仮想デ...
- しかし、C++では一つでも仮想関数があると、一般的にオーバ...
+クラスオブジェクトのサイズが増える。これは、仮想関数を処...
+適切な関数を呼び出すためにv-tableを参照するため、関数コ...
**オーバヘッドを回避するにはどうすればよいか? [#u98468dc]
-非常に多くの小さなクラスオブジェクトがある場合、メモリサ...
-しかし、仮想関数の無い基底クラスを定義すると、メモリリー...
~
***オーバヘッドを回避する方法 [#u3e45ae0]
+仮想関数の無い基底クラスを用意し、すべての継承クラスから...
+仮想関数の無い基底クラスを用意し、基底クラスのポインタを...
+専用のアロケーターを使ってクラスオブジェクトを生成する。...
*結論 [#c5ffefe5]
- ''通常は、基底クラスのデストラクタは、仮想にする。''
- ''仮想関数を一つも持たない基底クラスで、速度やメモリサ...
- ''基底クラスでのdeleteが不可欠な場合は、boost::poolの様...
- ''基底クラスのpublicな非仮想デストラクタは使用禁止!''
#back
[[ssacontents]]
作成中です
終了行:
*親クラスの非仮想デストラクタについて [#fb64cc10]
**基底クラスのデストラクタを仮想(virtual)にする理由 [#fd7...
-C++の入門書には、必ず「基底クラスのデストラクタはvirtual...
-理由は、サブクラスのオブジェクトを基底クラスのポインタと...
非仮想な基底クラス
class Super {
public:
Super(){}
~Super(){} // virtualでない
};
// サブクラス
class Sub : public Super {
public:
Sub()
: m_sub(new int[10])
{}
~Sub() {
delete [] m_sub;
}
private:
int* m_sub;
};
Super* super = new Sub; // 基底クラスのポインタとしてsub...
...
delete super; // Superのデストラクタは仮想ではないため、
// Subのデストラクタは呼ばれない。(コンパ...
// superが実はSubのポインタだということを...
// べがない)
Sub::m_subがメモリリークする!
もしSuperのデストラクタが仮想の場合、
Super* super = new Sub; // 基底クラスのポインタとしてsub...
// superには仮想関数を処理するた...
// v-tableという領域(の*)が付加...
...
delete super; // Superのデストラクタは仮想なので、v-tabl...
// 参照し、Subのデストラクタが呼ばれた後に
// Superのデストラクタが呼ばれる。したがっ...
// メモリリークは発生しない。
**仮想デストラクタがあると何が起こるか? [#mb28f764]
C++のメモリ管理と仮想関数の仕組み
(+文字はコンパイラによって自動的に追加されるコード)
// クラス定義
class Super {
+ struct _vtable_t {
+ void (*destructor)();
+ }
+ static _vtable_t _vtable = { &~Super };
+ _vtable_t* _p_vtable;};
public:
Super(){}
virtual ~Super(){}
private:
int m_super;
};
// サブクラス
class Sub : public Super {
+ static _vtable_t _vtable = { &~Sub };
public:
Sub() : m_sub(new int[10]) {}
~Sub() { delete [] m_sub; }
private:
int* m_sub;
};
newとdelete時の動作
Super* super = new Sub;
+ super = (Super*)malloc(sizeof(Sub));
+ super->_p_vtable = &Sub::_vtable;
+ Sub::Sub(super); // コンストラクタを呼び出す
.....
delete super;
+ super->_p_vtable->destructor(); // Sub::~Sub()が呼ばれる
+ free((void*)super); // メモリ管理システムにより、malloc
// したときのメモリブロックが解放...
- メモリリークを回避するため、すべての基底クラスは仮想デ...
- しかし、C++では一つでも仮想関数があると、一般的にオーバ...
+クラスオブジェクトのサイズが増える。これは、仮想関数を処...
+適切な関数を呼び出すためにv-tableを参照するため、関数コ...
**オーバヘッドを回避するにはどうすればよいか? [#u98468dc]
-非常に多くの小さなクラスオブジェクトがある場合、メモリサ...
-しかし、仮想関数の無い基底クラスを定義すると、メモリリー...
~
***オーバヘッドを回避する方法 [#u3e45ae0]
+仮想関数の無い基底クラスを用意し、すべての継承クラスから...
+仮想関数の無い基底クラスを用意し、基底クラスのポインタを...
+専用のアロケーターを使ってクラスオブジェクトを生成する。...
*結論 [#c5ffefe5]
- ''通常は、基底クラスのデストラクタは、仮想にする。''
- ''仮想関数を一つも持たない基底クラスで、速度やメモリサ...
- ''基底クラスでのdeleteが不可欠な場合は、boost::poolの様...
- ''基底クラスのpublicな非仮想デストラクタは使用禁止!''
#back
[[ssacontents]]
作成中です
ページ名: