0

我有两个要从基类派生的类,因为它们共享极其相似的函数和成员变量,而这两个类之间的唯一主要区别是SomeClassvs SomeOtherClassfor algo。解决此类问题的最佳方法是什么?

class A
{
    virtual doSomething(); // is it possible to implement it here instead so I don't repeat code?
    int shared_param_1;
    int shared_param_2;
}
class SGBM : public A
{
    SGBM()
    {
        algo->SGBMSpecificFunction();
    }

    std::shared_ptr<SomeClass> algo;

    doSomething()
    {
        algo->compute();
        // long code
    }

    int SGBM_param_1;
    int SGBM_param_2;
}
class BM : public A
{
    BM()
    {
        algo->BMSpecificFunction();
    }

    std::shared_ptr<SomeOtherClass> algo;

    doSomething()
    {
        algo->compute();
        // long completely similar code relying on algo
    }

    int BM_param_1;
    int BM_param_2;
}

谢谢!

4

3 回答 3

1

我认为最常见的方法是使用策略模式SomeClass,即SomeOtherClass需要从一个公共接口派生,您将通过构造函数将算法注入基类:

class Algorithm
{
public:
  virtual ~Algorithm() = default;
  virtual void algo() = 0;
};

class SomeClass : public Algorithm
{
public:
  void algo() override;
};

class SomeOtherClass : public Algorithm
{
public:
  void algo() override;
};

class A
{
public:
  explicit A(std::unique_ptr<Algorithm> algorithm)
    : algorithm{std::move(algorithm)} {}

  void do_something() { algorithm->algo(); }
private:
  std::unique_ptr<Algorithm> algorithm;
};

class SGBM : public A
{
public:
  explicit SGBM() : A{std::make_unique<SomeClass>()} {}
};

class BM : public A
{
public:
  explicit BM() : A{std::make_unique<SomeOtherClass>()} {}
};

但是,这要求您能够修改SomeClassSomeOtherClass(或编写包装器)。如果这不方便,您也可以为此使用CRTP

template <typename Concrete>
class A
{
public:
  void do_something() { static_cast<Concrete*>(this)->algo->compute(); }
};

class SGBM : public A<SGBM>
{
private:
    std::shared_ptr<SomeClass> algo;
    friend class A<SGBM>;
};

class BM : public A<BM>
{
private:
    std::shared_ptr<SomeOtherClass> algo;
    friend class A<BM>;
};

如果您需要一个通用的基类,BM并且SGBM需要引入一个额外的基类,A然后继承该基类。

于 2021-03-01T15:08:49.477 回答
0
class A
{
    virtual doSomething(); // is it possible to implement it here instead so I don't repeat code?
    void doComputing()
    {
        doSomething();
        // common code here
    }
    
    int shared_param_1;
    int shared_param_2;
}
class SGBM : public A
{
    std::shared_ptr<SomeClass> algo;
    doSomething()
    {
        algo->compute();
    }
    int SGBM_param_1;
    int SGBM_param_2;
}
class BM : public A
{
    std::shared_ptr<SomeOtherClass> algo;
    doSomething()
    {
        algo->compute();
    }
    int BM_param_1;
    int BM_param_2;
}

于 2021-03-01T15:06:43.027 回答
0

您正在尝试做的事情称为Strategy design pattern. 这是一种行为模式,可让您即时切换不同的算法。

可以在这里找到一个起点

您可以按如下方式实现它:

#include <iostream>
#include <memory>

// abstract algo
class Algo
{
public:
    void doSomething() { compute(); } // calling compute methods of child classes

    virtual ~Algo() = default;

private:
    virtual void compute() = 0; // Algo::compute() is a virtual function to be implemented in child classes
};

class SGBM  : public Algo
{
private:
    //each algo implements its own compute method
    void compute() override
    {
        std::cout << "Algo SGBM " << std::endl;
    }
};

class BM : public Algo
{
private:
    void compute() override
    {
        std::cout << "Algo BM" << std::endl;
    }
};

//not
class Context
{
private:
    std::unique_ptr<Algo> algo;

public:
    Context( std::unique_ptr<Algo> new_strategie): algo(std::move(new_strategie))
    {}

    void doSomething()
    {
        algo->doSomething();
    }

    void setAlgorithme(std::unique_ptr<Algo> new_strategie)
    {
        algo = std::move(new_strategie);
    }
};

int main()
{
     //  Treat algo BM
    Context context(std::make_unique<BM>());
    context.doSomething();
        // Treat algo SGBM
    context.setAlgorithme(std::make_unique<SGBM>());
    context.doSomething();


    return 0;
 }

此代码将输出:

Algo BM                                                                                                                                                                            
Algo SGBM
于 2021-03-01T15:19:05.437 回答