Я использую шаблон метода в своем проекте, как показано ниже

class Template
{
public:
void algorithm();
{
    A();
    B();
}
private:
virtual void A()=0;
virtual void B()=0;
}

У меня есть несколько подклассов, реализующих метод A и B по-разному.
Но теперь мне нужен новый класс Template2 для реализации немного другого алгоритма.

class Template2
{
public:
void algorithm();
{
    A();
    B();
    C();
}
private:
virtual void A()=0;
virtual void B()=0;
void C()
{
    //some stuff
    A();
    //some stuff
    B();
}
}

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

< Ет > ИЗМЕНИТЬ
Извините, я не разъяснил свою точку зрения.
Теперь у меня есть две иерархии наследования.
1. Абстрактный класс Template и некоторые подклассы A1,A2,A3,A4...
2. Абстрактный класс Template2 и некоторые подклассы B1,B2,B3,B4...
Это нормально работает, но мне интересно, есть ли способ каким-то образом объединить эти две иерархии, потому что A1 и B1 имеют один и тот же код, за исключением того, что они получены из Template и Template2 соответственно.
Для меня не имеет значения, является ли решение шаблоном метода шаблона
У меня работают оба ответа bcperth и Spotted :)
Большое спасибо.

1
LtChang 1 Окт 2018 в 18:11

2 ответа

Лучший ответ

Я согласен с Spotted, но рассматривали ли вы возможность просто добавить дополнительные алгоритмы в свой класс template? Это все еще шаблон шаблона с несколькими алгоритмами. Вы получаете более толстый класс, но без повторения кода. Ниже представлена иллюстрация.

#include <iostream>

using namespace std;

class Template
{
public:
    void algorithm1()
    {
        A();
        B();
    }

    void algorithm2()
    {
        A();
        B();
        C();
    }

private: void C()
    {
    cout << endl << "start C() ";
    A();
    cout << "middle C() ";
    B();
    cout << "end C()" << endl;
    }

private:
    virtual void A() = 0;
    virtual void B() = 0;
};

class real :public Template {

    void A() { cout << "A(1)  "; }
    void B() { cout << "B(1) "; }
};

int main()
{
    real Real;
    cout << "algorithm1" <<endl;
    Real.algorithm1();
    cout << endl;
    cout << endl << "algorithm2 << endl";
    Real.algorithm2();

    return 0;
}
2
bcperth 2 Окт 2018 в 07:16

Во-первых, простите мой плохой синтаксис C ++.

Я предлагаю вам отделить A() и B() от Template, чтобы вам было легче повторно использовать их в Template2

class Strategy
{
    public:
    virtual void A()=0;
    virtual void B()=0;
}

Тогда имейте общего предка между Template и Template2:

class AbstractTemplate
{
    public:
    virtual void algorithm()=0;
}

И, наконец, реализация Template и Template2 как "финальных" классов (= нет необходимости в подклассах).

class Template : AbstractTemplate
{
    public:
    Template(Strategy strategy)
    {
        this.strategy = strategy;
    }
    void algorithm()
    {
        strategy.A();
        strategy.B();
    }
    private:
    Strategy strategy;
}

class Template2 : AbstractTemplate
{
    public:
    Template2(Strategy strategy)
    {
        this.strategy = strategy;
    }
    void algorithm()
    {
        strategy.A();
        strategy.B();
        C();
    }
    private:
    Strategy strategy;
    void C()
    {
        //some stuff
        strategy.A();
        //some stuff
        strategy.B();
    }
}

Перекрытие между Template и Template2 минимально (учитывая, что вам не нужны подклассы, я думаю, это нормально).

1
Spotted 2 Окт 2018 в 05:45