Как избежать C ++ броска для определенных методов класса?Шаблон дизайна? - PullRequest
1 голос
/ 25 марта 2011

Предположим, у меня есть что-то вроде этого:

class Father {
    public:
      virtual int genericMethod (void) =0;
  };

class Son1: public Father {
  public:
    int genericMethod ()
      { }
  };

class Son2: public Father {
  public:
    int genericMethod ()
      { }
    int specifClassMethod()
      { }
  };

В основном я делаю следующее:

Father * test = new Son2();

test->specifClassMethod(); //Can't do this! It is specific of Class Son2 and is not a virtual method in class Father!

Главный вопрос здесь заключается в том, чтобы узнать лучший способ доступа к конкретному Son2метод через интерфейс отца.Я хочу знать, есть ли Шаблон проектирования, чтобы решить тот или иной путь.Я не хочу делать броски, и я не хочу вставлять много «если» в мой код.

С уважением,

Эдуардо

Ответы [ 7 ]

2 голосов
/ 25 марта 2011

Может быть, Шаблон посетителя - это шаблон, который вы ищете.

Как шаблон посетителя избежать снижения рейтинга

2 голосов
/ 25 марта 2011

Возможный подход состоит в том, чтобы иметь определенный интерфейс с дополнительными методами и виртуальный метод для получения этого интерфейса в базовом классе (который может возвращать ноль):

class SpecificInterface {
public:
  virtual ~SpecificInterface()
  { }
  virtual int specifClassCmethod() = 0;
  { }
};

class Father {
  public:
    virtual int genericMethod (void) = 0;
    virtual SpecificInterface* getSpecificInterface (void) =0;
};

class Son1: public Father {
  public:
    int genericMethod ()
      { }
    SpecificInterface* getSpecificInterface (void)
      { return 0; }
  };

class Son2: public Father, public SpecificInterface {
  public:
    int genericMethod ()
      { }
    int specifClassCmethod()
      { }
    SpecificInterface* getSpecificInterface (void)
      { return this; }
  };

Использование следующее:

Father * test = new Son1();
SpecificInterface * specificAPI = test->getSpecificInterface();
if( specificAPI )
  specificAPI->specifClassCmethod();
1 голос
/ 25 марта 2011

Вы также не могли юридически решить это с помощью приведения, потому что «тест» указывает на объект «Отец», а не на объект «Сын2».Приведение типов объектов означает «Поверьте мне, компилятор, эта переменная на самом деле содержит X».Он каким-то образом не преобразует магически базовый объект в производный объект;он только сообщает компилятору то, что вы уже знаете, что он этого не делает.

Если вы хотите, чтобы поведение отличалось в зависимости от производного класса, то переместите поведение в виртуальный метод, т. е. код, который хочет вызвать specificCLassMethod) принадлежит виртуальному методу Отца.

0 голосов
/ 25 марта 2011

Прежде всего, вы не можете создать экземпляр для класса "Father", потому что это абстрактный класс (который имеет виртуальную int genericMethod (void) = 0; -pure виртуальную функцию). Вместо этого можно назначить экземплярэто ....

Как

Son1* obj_son = new Son1();
Father* obj = obj_son;
//now if you call generic method - son1 method will be called(Father method is over ridden)
obj->genericMethod();
//similarly for son2 class
Son2* obj_son2 = new Son2();
Father* obj2 = obj_son2;
obj2->genericMethod();
obj2->specifClassCmethod();
0 голосов
/ 25 марта 2011

Если у вас действительно есть что-то конкретное для Son2, тогда вам следует использовать dynamic_cast<>. Если это что-то, что может быть добавлено в качестве виртуальной функции в базовый класс с пустым поведением по умолчанию, то вы можете решить свою проблему без приведения (но это не то, что вы хотели сделать, как вы указали в вопросе)

Один шаблон проектирования для решения вашей проблемы - это использование прокси-объекта . Этот объект будет иметь все методы, которые могут быть вызваны, и делегировать их реальному объекту или нет.

Преимущества прокси-шаблона:

  • вы концентрируете логику, необходимую для дифференциации объектов позади, в одно место
  • Вы можете легко добавить запись в журнал
  • код клиента остается простым, а классы Son очищаются от лишних вещей
0 голосов
/ 25 марта 2011

Вы можете static_cast<Son2*>(test)->specifClassCmethod();, но это работает, только если Father * test = new Son2();

0 голосов
/ 25 марта 2011

Нет. Чтобы вызывать методы, которые существуют только в дочернем классе, вам придется привести к классу ребенка.

Хотя вы можете создать карту, которая отображает имена функций на функции, добавьте в нее свои функции из конструктора дочернего класса, а затем используйте что-то вроде test->callMethod("name");, вам нужно сделать так, чтобы все эти методы имели одинаковую сигнатуру или использовали varargs для передачи аргументов, что не очень приятно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...