2009-12-04 4 views
1

Этот вопрос кажется, что это может быть несколько обычным явлением, но я не нашел ничего, когда стряхивал StackOverflow или interwebs.Вызов метода класса Child при обработке списка объектов класса родителя

Я столкнулся с методом в классе C++, который принимает список объектов (например) Parent. В этом примере предположим, что существуют два класса, которые производятся от Parent: Child1 и Child2.

Для каждого объекта в списке, то метод проверяет, является ли объект типа Child2 (через IsOfType() метод, который каждый класс реализует), и если да, то он вызывает метод, который только предоставленный Child2 класса.

Это проблема в том, что метод обработки списка не может обрабатывать каждый объект одинаково? Я видел, как это делалось и в других местах, поэтому, похоже, в какой-то степени это может быть обычной практикой.

Один из вариантов может заключаться в том, чтобы объявить метод Child2 в классе Parent, чтобы все объекты Parent реализовали его. Однако в этом случае только класс Child2 фактически реализует любое поведение при переопределении метода.

Ваши мысли? Заранее спасибо!

ответ

1

Если ваш тест IsOfType() проходит, вы можете отнести родительский объект (указатель на) к объекту Child2 и получить доступ к его конкретным функциям-членам.

EDIT: Это зависит от вашего дизайна и от того, насколько строго вы гарантируете, что реализация IsOfType() даст правильные ответы (т. Е. Она также работает, когда вы добавляете новые подклассы в неделю). Возможно, было бы безопаснее использовать встроенный Typeid. Реализация любого возможного метода, который любой ребенок когда-либо имел бы в родительском объекте, был бы трудным, поэтому повышение уровня приветствуется, когда метод действительно семантически специфичен для класса Child2.

+0

В настоящее время метод обработки списка ведет себя так, как вы описали, только он не использует Typeid.Возможно, метод может оставаться как есть на данный момент, но, возможно, использовать Typeid вместо метода IsOfType(). Спасибо за это предложение! – bporter

3

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

class Parent { 
public: 
    virtual int doSomething() {} 
}; 

class Child1 : public Parent { 
}; 

class Child2 : public Parent { 
public: 
    virtual int doSomething(); 

Теперь вы просто опустить вызов IsOfType вообще и вызвать DoSomething на всех указателей, переданных вами.

Единственная веская причина, по которой я могу думать о том, почему у вас есть функция IsOfType, является то, что вы не имеете контроля над классом родителя и не можете изменить его, чтобы добавить метод doSomething.

+0

Плохо, если doSomething имеет аргументы, и только Child2 знает тип этих аргументов –

+2

@Alexey, если это так, то я думаю, что это плохой дизайн, и это не проблема, которая действительно подходит для полиморфизма. – Glen

+0

В противном случае, если вам нехорошо иметь doSomething() в интерфейсе Parent, возможно, вы скорее сохраните экземпляры Child1 и Child2 в двух отдельных списках. Возможно, Child1 и Child2 не имеют достаточно общего, чтобы гарантировать их смешивание в одном списке. – digitalarbeiter

2

Вы можете объявить новый метод в интерфейсе, который реализует только Child2. Затем вы можете использовать dynamic_cast<ISomeOtherInterface>, чтобы узнать, поддерживает ли объект расширенную функцию. Этот приведение приведет к указателю null для объектов, которые не поддерживают дополнительный интерфейс.

Это позволит вам создавать другие объекты, которые реализуют эту функцию, не требуя, чтобы ваша обработка списка знала о каждом конкретном типе объекта.

+0

Это может быть очень хороший подход. Спасибо за предложение! – bporter

0

Возможно, вы найдете Visitor Pattern, пригодный для использования в этом случае. Это позволит самим объектам (child1, child2 и т. Д.) Перезвонить вам с их статическим типом и предпринять соответствующие действия.

Смежные вопросы