Как использовать функции из производного класса, не добавляя их в базовый класс - PullRequest
0 голосов
/ 02 января 2019

Скорее всего, это глупый вопрос, но я не могу понять, возможно ли это вообще и нужно ли это на самом деле.

Скажем, какой-то код во многом зависит от использования определенноговиртуальный базовый класс, действующий как интерфейс и затем выводящий несколько подклассов, которые реализуют виртуальные методы базового класса.Можно ли использовать функциональность, которой нет в базовом классе (интерфейсе) ниже, без полного игнорирования твердых принципов, когда остальная часть программы не должна видеть ничего, кроме «интерфейса» базового класса?Как в примере ниже, возможно ли использовать bar () из класса B внутри функции, которая знает только об A?И я должен просто добавить bar () к «интерфейсу» вместо этого?

// Base class - "interface"
Class A
{
    public:
        virtual int foo();
}

// Derived class - implementing the "interface" + more
Class B: public A
{
    public:
        int foo();
        int bar();
}

int main()
{

    function(A); // Some magic function that would utlize the bar() method

    return 0;
}

1 Ответ

0 голосов
/ 02 января 2019

Короткий ответ - да, используйте оператор dynamic_cast (но см. Ниже).Волшебная функция будет выглядеть примерно так:

void function(A& a)
{
  B* b = dynamic_cast<B*>(&a);
  if (b)
  {
    // Object is a B...
    b->bar();
  }
  else
  {
    // fallback logic using only methods on A
  }
}

Но учтите, что многие программисты считают это запахом кода.В частности, если нет способа реализовать «запасную» ветвь, то она предлагает, чтобы функция действительно принимала B, и что-то в дизайне может быть ошибочным.(Трудно сказать, когда говорите в таких общих чертах, однако.) Также имейте в виду, что dynamic_cast может быть дорогим, особенно со сложной иерархией классов.

Если это вообще разумно, предпочтительнее переместить B-специфическая логика в класс B как-то.Вы можете также рассмотреть вопрос о том, чтобы сделать метод bar членом класса A (A обеспечит некоторую разумную реализацию по умолчанию).Другой подход может состоять в том, чтобы создать новый интерфейс для хранения метода bar и заставить вашу функцию принимать объект этого типа.(Класс B будет реализовывать как A, так и новый интерфейс.)

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