Есть ли способ использовать реализацию «сестринской» функции в классе, производном от абстрактного класса? - PullRequest
2 голосов
/ 06 мая 2020

У меня проблема с дизайном. Я хотел бы использовать реализацию функции из "сестринского" класса при наследовании от абстрактного класса, если это возможно.

Проблема

У меня есть некоторый код «history c», который добавляет поведение к базовому классу с использованием наследования.

Старый код

///////////////// Historic code ////////////////:

class IBase
{
    int value;
    virtual int method(){
        return value;
    };
}

class DerivedHist : IBase {
    void otherMethod(){
        return;
    }
}

Новый код

После некоторых изменений я закончил специализацию IBase в 2 производных классах ( Derived1 и Derived2) и изменили класс IBase на абстрактный класс. Проблема в том, что я хотел бы добавить поведение класса DerivedHist к обоим классам, и я не понимаю, как это сделать правильно.

///////////////////// New code //////////////////////////:

//this time IBase is an abstract class
class IBase
{
    int value;
    virtual int method() = 0;
}

class DerivedHist : IBase {
    void otherMethod(){
        return;
    }

    //I'd like to use Derived1's or Derived2's implementation
    virtual int method(){
        //???
    }
}

class Derived1 : IBase {
    virtual int method(){
        return 2*value;
    }
}

class Derived2 : IBase {
    virtual int method(){
        return 3*value;
    }
}

Я не понимаю, как именно верните класс DerivedHist на место ...

Решения

Я придумал несколько идей:

  1. Напишите 2 класса, эквивалентные DerivedHist, которые наследуют из Derived1 (скажем, Derived1Hist) и из Derived2 (скажем, Derived2Hist), но это означает наличие двух классов с почти одинаковым кодом.

                                    IBase
                                    /   \
                            Derived1    Derived2
                            /               \
                        Derived1Hist        Derived2Hist
    
  2. Использование чего-то вроде этого в конструкторе DerivedHist:

    DerivedHist(IBase* other) : IBase(*other){
        ...
    }
    

    и вызовите его с помощью динамического c cast:

    Derived1 derived1(...);
    DerivedHist derivedHist(dynamic_cast<IBase*>(derived1));
    

    Разве при этом не использовалась бы правильная реализация метода ()? Поскольку мы можем вызвать dynamic_cast (new Derived1 (...)) -> method (), я представил, что передача чего-то подобного в конструкторе копирования может сработать. Мне не удалось найти способ компиляции кода с чем-то вроде этого ...

  3. Сделать один из объектов Derived [1,2] членом

    class DerivedHist : IBase {
        IBase* methodHolder;
    
        DerivedHist(IBase* other) : methodHolder(other){
            ...
        }
    
        void otherMethod(){
            return;
        }
    
        virtual int method(){
            //here I'd have to copy the relevant data members to the other object
            methodHolder->value = value;
            //and then call the other method
            return methodHolder->method();
        }
    }
    

    Это похоже на лучшее решение для 3.

    Но здесь проблема, которую я вижу, заключается в том, что у меня нет данных, синхронизированных из DerivedHist и его члена methodHolder.

    Я мог бы отслеживать все изменения и применять его к methodHolder, но это не кажется идеальным решением.

Резюме

Подводя итог, у меня есть два основных вопроса: следующее:

  1. Есть ли способ вызвать реализацию метода () из другого производного класса?
  2. В противном случае, какой шаблон мне следует использовать для решения этой проблемы?
...