2016-11-02 9 views
1

C++で以下の簡単な継承の例があります。私の理解へオーバーライドされた仮想メソッドは、引き続き基本クラスのfunctionを呼び出します。

#include<bits/stdc++.h> 

using namespace std; 

class Animal{ 
    public: 
    string mName; 

    Animal(string pName){ 
     mName=pName; 
    } 

    virtual void printAnimal(){ 
     cout<<"Animal "<<this->mName<<endl; 
    } 

}; 

class Dog: public Animal{ 

    public: 
    Dog(string pName): Animal(pName){} 

    void printAnimal(){ 
     cout<<"Dog "<<this->mName<<endl; 
    } 
}; 

class Cat: public Animal{ 
    public: 

    Cat(string pName): Animal(pName){} 


    void printAnimal(){ 
     cout<<"Cat "<<this->mName<<endl; 
    } 
}; 

Animal getCat(){ 
    return Cat("Tom"); 
} 

Animal getDog(){ 
    return Dog("Scooby"); 
} 

int main(){ 
    getCat().printAnimal(); 
    getDog().printAnimal(); 
} 

、我々は、基底クラスに与えられた仮想関数をオーバーライドする場合、オーバーライド関数が呼び出されたときに参照が基底クラスや派生クラスにあるかどうかに関係なく、それが呼び出す必要があります基本クラスではなく、派生クラスで定義された関数です。

だから、1は上記のプログラムの出力があることを期待する、

Cat Tom 
Dog Scooby 

しかし、私は取得、

Animal Tom 
Animal Scooby 

ですが、なぜでしょうか?これを行う正しい方法は何ですか?

+5

[object slicing](http://stackoverflow.com/questions/274626/what-is-object-slicing)を参照してください。多型が機能するには、ポインタや参照を使用する必要があります。私は['std :: unique_ptr'](http://en.cppreference.com/w/cpp/memory/unique_ptr)を調べることをお勧めします。 –

+0

ありがとう! unique_ptrはこのような状況に対応するための標準的な方法ですか? – samurdhilbk

+0

たぶんそれは私ですが、なぜ 'mName'は公開されていますか? –

答えて

2

あなたは@dude言及としてをスライスオブジェクトからオブジェクトを防止するために、代わりのshared_ptrを渡すことができ:Demo

shared_ptr<Animal> getCat(){ 
    return make_shared<Cat>("Tom"); 
} 

shared_ptr<Animal> getDog(){ 
    return make_shared<Dog>("Scooby"); 
} 

int main(){ 
    getCat()->printAnimal(); 
    getDog()->printAnimal(); 
} 

編集:のように、メモリリークを防ぐためのshared_ptrへのポインタからの戻り値を変更コメントに正しく示唆されています。

+0

メモリリークを避けるためにこれらを削除することについて心配する必要はありませんか? – samurdhilbk

+0

そのようにオブジェクトがリークします。代わりにスマートポインタを使用します。 – Alex

+0

ありがとうございます。コードが変更されました。 –

関連する問題