2017-08-10 13 views
0

私はこのクラスのクラスを持っています。単純な例のC++多型

class Animal { 
public: 
    Animal(uint32_t attr1, uint32_t attr2); 

    virtual uint32_t get_attr1() const; 
    virtual uint32_t get_attr2() const; 

private: 
    uint32_t attr1; 
    uint32_t attr2; 
}; 

class Dog: public Animal { 
public: 
    Dog(uint32_t attr1, uint32_t attr2, uint32_t attr3); 
    uint32_t get_attr3() const; 

private: 
    uint32_t attr3; 
}; 

class Cat: public Animal { 
public: 
    Cat(uint32_t attr1, uint32_t attr2, uint32_t attr4); 
    uint32_t get_attr4() const; 

private: 
    uint32_t attr4; 
}; 

今、私は次のように宣言されている

vector<Animal*> animals; 

といくつかの機能を持つようにしたい:

void f(Dog* dog); 
void f(Cat* cat); 

と、このコード:多型を作るためにどのように

for (auto animal: animals) { 
    f(animal); 
} 

をこのコードの中から?それは、動物が猫や犬のように扱われていないように見えます。

+0

はなぜあなたが扱っていますベクトルへのポインタ?また、 'f'関数は' cat'クラスと 'dog'クラスのメンバでなければなりません。 – scohe001

+0

私はf関数が設計の選択のためにクラスのメンバであることを望みません。しかし、ポインタに同意する – tomtom

+1

このように設定している場合は、[dynamic_cast](http://en.cppreference.com/w/cpp/language/dynamic_cast)を参照してください。 – scohe001

答えて

4

f()オーバーロードがAnimal*を入力とすると、forループが作成されたとおりに動作します。その後、DogCatのために別々のf()オーバーロードを呼び出すには、実行時にdynamic_castを使用する必要があります、例えば:

void f(Dog* dog) 
{ 
    // do something only a dog can do ... 
} 

void f(Cat* cat) 
{ 
    // do something only a cat can do ... 
} 

void f(Animal *animal) 
{ 
    if (Dog *dog = dynamic_cast<Dog*>(animal)) { 
     f(dog); 
    } 
    else if (Cat *cat = dynamic_cast<Cat*>(animal)) { 
     f(cat); 
    } 
} 

... 

for (auto animal: animals) { 
    f(animal); 
} 

しかし、これは多型の原則に反します。 f()ニーズは、それが上と呼ばれAnimalの種類に応じて異なることを行う場合、それはAnimalクラスの仮想メソッドであるべきであり、必要に応じて、その後の子孫は、それを上書きすることができます。

class Animal { 
public: 
    ... 
    virtual ~Animal() {} // <-- don't forget this! 
    ... 
    virtual void f() = 0; 
}; 

class Dog: public Animal { 
public: 
    ... 
    void f() override; 
}; 

class Cat: public Animal { 
public: 
    ... 
    void f() override; 
}; 

void Dog::f() 
{ 
    // do something only a dog can do ... 
} 

void Cat::f() 
{ 
    // do something only a cat can do ... 
} 

... 

for (auto animal: animals) { 
    animal->f(); 
} 
+0

また、追加することを避けるために[訪問者パターン](https://stackoverflow.com/documentation/design-patterns/4579/visitor-pattern/15127/visitor-pattern-example-in-c#t=201708110127395809679)があります多くの仮想メソッド。 – Jarod42