Объединить два класса в общий базовый класс (шаблон? Mixin?) - PullRequest
0 голосов
/ 01 июля 2018

Мы используем стороннюю библиотеку для управления специализированной PCI-картой. Поставщик выпустил новую карту, которая использует новый класс для управления им, но новый класс имеет те же методы, что и старый.

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

Я думаю, что это случай для mixin , но я не уверен. Код ниже показывает ситуацию.

Переопределение каждого метода в классе шаблона возможно, но в APIClass1 и APIClass2 существует множество методов. (методы имеют одинаковое имя и подпись). Я имею в виду что-то вроде: void one() { TBase::one(); }

Есть ли способ в C ++ сделать это без дублирования большого количества кода?

#include <stdio.h>

class APIClass1
{
public:
    void one() { printf("APIClass1 ONE\n"); }
    void two() { printf("APIClass1 TWO\n"); }
};

class APIClass2
{
public:
    void one() { printf("APIClass2 ONE\n"); }
    void two() { printf("APIClass2 TWO\n"); }
};

class MasterClassBC
{ };

template <class T>
class MasterClass : public T, public MasterClassBC
{
public:
    typedef T TBase;
};

int main(int argc, char *argv[])
{
    // Use pointer to base class object
    MasterClassBC *pBc;
    if (isNewCard())
        pBc = new MasterClass<APIClass2>;
    else
        pBc = new MasterClass<APIClass1>;

    pBc->two(); // error:‘class MasterClassBC’ has no member named ‘two’
}

РЕДАКТИРОВАТЬ I

По предложению StoryTeller, я почти все заработал, поместив чисто базовые функции в базовый класс. Новая проблема заключается в том, что некоторые функции имеют разные подписи между APIClass1 и APIClass2.

В приведенном ниже примере мы имеем void three() и void three(int n).

Я попытался создать newThree(), который вызывает соответствующую функцию во время выполнения, но не компилируется, так как в TBase отсутствует один или другой метод three в зависимости от специализации.

class APIClass1
{
public:
    void one() { printf("APIClass1 ONE\n"); }
    void two() { printf("APIClass1 TWO\n"); }
    void three() { printf("APIClass1 THREE\n"); }
};

class APIClass2
{
public:
    void one() { printf("APIClass2 ONE\n"); }
    void two() { printf("APIClass2 TWO\n"); }
    void three(int n) { printf("APIClass2 THREE: %d\n", n); }
};

class MasterClassBC
{
    virtual void one() = 0;
    virtual void two() = 0;
    virtual void newThree() = 0
};

template <class T>
class MasterClass : public T, public MasterClassBC
{
public:
    typedef T TBase;
    MasterClass(bool useApi1 = true) : mUseApi1(useApi1) {}

    void setTheNumber(int n) { mTheNumber = n; }

    void one() { TBase::one(); }
    void two() { TBase::two(); }

    void newThree()
    {
        if (mUseApi1)
            TBase::three();
        else
            TBase::three(mTheNumber);
    }

private:
    bool mUseApi1;
    int  mTheNumber;
};
...