2016-12-23 3 views
1

У меня есть две специализированные объекты:Есть ли способ, чтобы специализироваться общий метод наследуемого объекта

class Food {}; 
class Fruit : public Food {}; 
class Vegetable : public Food {}; 

Тогда у меня есть родительский класс, который будет наследоваться:

class Parent 
{ 
    virtual void say(Food* obj) { std::cout << "The object is food" << std::endl; } 
}; 

И наследственное класс от родителя.

class Child : public Parent 
{ 
    virtual void say(Fruit* obj) { std::cout << "The object is a fruit" << std::endl; } 
    virtual void say(Vegetable* obj) { std::cout << "The object is a vegetable" << std::endl; } 
}; 

я:

std::vector<Food*> basket; 
Fruit fruit = Fruit(); 
Vegetable vegetable = Vegetable(); 
basket.push_back(&fruit); 
basket.push_back(&vegetable); 

Child child = Child(); 

for (Food* food : basket) 
{ 
    child.say(food); 
} 

Я хотел бы, чтобы напечатать «Объект является плодом», а затем «Объект представляет собой овощ», но он не работает: я получаю сообщение об ошибке: неизвестное преобразование для аргумента 1 из «Пища *» в «Фрукты *».

Есть ли способ сделать это, не используя typeid, если это возможно, потому что я слышал, что это накладные расходы. Вот код в онлайн-редакторе: cpp.sh/27ekc

+1

Различные продукты должны печатать себя полиморфно. Затем вы просто вызываете эту функцию в своей функции 'say'. – NathanOliver

+4

В реальном мире ребенок знает, что она есть. В ООП еда знает свое имя. – Arkadiy

+0

Я думаю, проблема в том, что вы не можете вызвать перегруженный метод, ожидающий полиморфизма, чтобы выяснить, какой метод вызывать. –

ответ

3

Я думаю, что соответствующее решение этой проблемы заключается в следующем:

class Food 
{ 
public: 
    virtual ~Food() = default; 
    virtual void say() const; 
}; 
class Fruit : public Food 
{ 
public: 
    void say() const override { std::cout << "The object is a fruit" << std::endl; } 
}; 
class Vegetable : public Food 
{ 
public: 
    void say() const override { std::cout << "The object is a vegetable" << std::endl; } 
}; 

class Parent 
{ 
public: 
    virtual ~Parent() = default; 
    virtual void say(const Food& obj) const { obj.say(); } 
}; 

class Child : public Parent {}; 

int main() 
{ 
    std::vector<Food*> basket; 
    Fruit fruit = Fruit(); 
    Vegetable vegetable = Vegetable(); 
    basket.push_back(&fruit); 
    basket.push_back(&vegetable); 

    Child child = Child(); 

    for (const Food* food : basket) 
    { 
     child.say(*food); 
    } 
} 

EDIT: в соответствии с вашим комментарием, он основан на том, что вы имеете в виду здоровье , интерпретировать его как-то вдоль этих линий:

class Food 
{ 
public: 
    virtual ~Food() = default; 
    virtual void say() const; 
    virtual int health() const; 
}; 
class Fruit : public Food 
{ 
public: 
    void say() const override { std::cout << "The object is a fruit" << std::endl; } 
    int health() const override { return 5; } 
}; 
class Vegetable : public Food 
{ 
public: 
    void say() const override { std::cout << "The object is a vegetable" << std::endl; } 
    int health() const override { return 10; } 
}; 

class Parent 
{ 
public: 
    virtual ~Parent() = default; 
    virtual void say(const Food& obj) const { obj.say(); } 
}; 

class Child : public Parent 
{ 
    int health; 

public: 
    void eat(const Food& obj) { health += obj.health(); } 
}; 

int main() 
{ 
    std::vector<Food*> basket; 
    Fruit fruit = Fruit(); 
    Vegetable vegetable = Vegetable(); 
    basket.push_back(&fruit); 
    basket.push_back(&vegetable); 

    Child child = Child(); 

    for (const Food* food : basket) 
    { 
     child.say(*food); 
     child.eat(*food); 
    } 
} 

Есть много различных способов сделать это.

+0

Большое спасибо за ваш ответ. Но что сказать, например, добавить здоровье к ребенку? – Talesseed

+0

@Talesseed: вы также можете посмотреть [шаблон посетителя] (http://stackoverflow.com/documentation/design-patterns/4579/visitor-pattern/15127/visitor-pattern-example-in-c#t=201612232223221431311) в качестве альтернативы для добавления метода в «Продовольствие». – Jarod42

+0

@ Jarod42 Спасибо, хотя и не использовал бы этот шаблон здесь, поскольку он будет комплексифицировать класс, который должен быть очень простым. – Talesseed