2016-11-26 7 views
-3

C++のサブクラスには疑問があります。私はこのコードを持っている:派生クラスのオブジェクトに、基底クラスのものではなく、独自の関数を使用させます。

class BaseClass() { 
    BaseClass(); 
    void doSomething(); 
} 

class SubClass : public BaseClass { 
    SubClass(); 
    void doSomething(); 
} 

私はそれがその後、私はdoSomethingのを(使用するFOOが必要...

BaseClass foo = SubClass(); 

をサブコンストラクタを呼び出すんサブクラスである可能性がBaseClassのオブジェクトを宣言する場合)方法は派生クラスのですが、私はこのようにします...

foo.doSomething(); 

派生クラスの代わりに親クラスメソッドを使用します。私はこれを試してみましたが、それは動作しません:

foo.SubClass::doSomething(); 

はそれを行う方法はありますか私は、それが独自の機能を利用するために「サブクラス」タイプのオブジェクトを宣言するように強制していますか?

+1

'virtual void doSomething();' ?? –

+3

'BaseClass foo = SubClass();' - 'foo'は' BaseClass'ではなく 'BaseClass'のオブジェクトです。これは**オブジェクトのスライス**の例です。 'doSomething()'バーチャルをマークしてもこれは変わりません。 –

+0

はい、Pete Beckerさんが問題をスライスしているようだから、関数を仮想化すると問題は解決しません...これを解決する唯一の方法は、fooをSubClass型として明示的に宣言することです。 – JotaEle

答えて

1

問題1:オブジェクトが匿名の一時​​オブジェクトを作成し、コピー構築BaseClassオブジェクトを、あなたの初期設定では

BaseClass foo = SubClass(); 

をスライス。つまり、fooは​​からコピーされたBaseClassのままです。

これはobject slicingと呼ばれます。 baseClassにデータメンバーがある場合は、そのサブクラスの対応するデータメンバーがそのメンバーにコピーされます。​​に追加のデータメンバーがある場合、これらは失われます。

あなたはBaseClassオブジェクトを操作したいのですが、ベースかどうかに派生、彼らの本当のタイプのメンバーを失うことなく、あなたが参照またはポインタを使用する必要がある場合:

BaseClass *foo = new SubClass; // foo is a base class pointer but points to a SubClass object. 

SubClass bar; 
BaseClass& foo2 = bar;   // foo2 is a base class REFERENCE which refers to a Subclass object 

しかし、これは十分ではありません。

問題2:多型

あなたは今メソッドを呼び出したい場合:

foo->doSomething(); 
foo2.doSomething(); 

それはまだオブジェクトの実際の型は言及/指摘にもかかわらず、呼び出されるだろうとBaseClass::doSomething()だろうに。これは、通常のメンバー関数の場合、コンパイラはコンパイル時に呼び出す関数を識別しようとします。コンパイル時には、ポインタや参照の型しか知りません。

多態性の恩恵を受けるには、Johanで説明されているように、関数をvirtualと定義する必要があります。この場合、コンパイラは、少しのオーバーヘッドでオブジェクトの型を動的に識別できるコードを生成するため、関数の正しいバージョンを期待通りに呼び出すことができます。

基本クラスに少なくとも1つの仮想関数がある場合は、仮想デストラクタを宣言することをお勧めします。

0

あなたは仮想使用

virtual void doSomething() 
{ 
    ---- 
} 
+0

このオブジェクト指向プログラミングの概念は多態性と呼ばれます –

2

のように、BaseClassの仮想dosomeThingメソッドを宣言し、オーバーライドすることができます。

class BaseClass() { 
    BaseClass(); 
    virtual ~BaseClass() = default; 
    virtual void doSomething(); 
} 

class SubClass : public BaseClass { 
    SubClass(); 
    void doSomething() override ; 
} 

編集を:クリストフは、上記のように仮想デストラクタを使用して、言ったように。

+0

しかし、ベターは仮想デストラクタを予知します。 – Christophe

関連する問題