c++ - 如何让子类在 C++ 中返回一个不太通用的 typedef?

标签 c++ oop templates inheritance design-patterns

免责声明:我明白以下可能不是正确的做事方式,并希望就我如何正确做事提出建议。

我有以下 typedef

typedef boost::adjacency_list<boost::setS, boost::vecS, boost::directedS, VertexProperties, boost::no_property, GraphProperties> Witness;

以及我的 Solver 界面中的以下函数。

virtual Witness solve(const Graph& graph) = 0;

我的意图是 Witness 将是 Solver.solve() 的(抽象)返回类型。我想实现从 Solver 继承的类并实现它们自己的函数 solve() 版本。其中一个类是 SpecialSolver : public Solver。这个 SpecialSolver 应该返回比 Witness 更专业的东西,比如 SpecialWitness。因此,SpecialSolversolve() 的实现应该如下所示。

Witness SpecialSolver::solve(const Graph& graph)
{
    SpecialWitness Special;

    // Do some stuff

    return Special;
}

我对 C++ 模板的了解并不好。我最初认为我可以做这样的事情:

typedef boost::adjacency_list<boost::setS, boost::vecS, boost::directedS, SpecialVertexProperties, boost::no_property, SpecialGraphProperties> SpecialWitness;

其中 SpecialVertexProperties : VertexPropertiesSpecialGraphProperties : GraphProperties。然后,SpecialWitness 将成为 Witness 的子类型,我将实现我想要的结果。 las,这是不正确的,我想知道正确的设计应该是什么?我怎样才能使 SpecialWitness 成为 Witness 的特殊形式,以便我可以编写所有实现的客户端 Solver,简单到求解器接口(interface)?

最佳答案

那样做是行不通的,您将成为名为“对象切片”的效果的牺牲品:

在您返回对象时,所有使 SpecialWitness 变得特别的东西都被切断,只有基类 Witness 部分保留下来。

如果您想以多态方式返回,则没有办法绕过引用或指针;当您在函数中创建对象时,您将选择指向动态分配对象的指针。

现在为了从一开始就防止内存泄漏,您将使用智能指针(甚至不会显示原始指针变体...):

std::unique_ptr<Witness> SpecialSolver::solve(const Graph& graph)
{
    auto special = std::make_unique<SpecialWitness>();

    // Do some stuff

    return special;
}

不过,最后,仔细看看 Witness 基类!

它是否打算完全继承(即它是否提供了一个虚拟析构函数——它没有 seem 所以!)?否则,您将在尝试删除对象时遇到麻烦。那么聚合是更好的方法:

class Witness
{
    boost::adjacency_list<...> m_aList;
public:
    virtual ~Witness() = default;

    // provide some appropriate interface...
};

编辑:继承会是什么样子?

class Witness
{
public:
    virtual ~Witness() = default;

    virtual void doSomething() { /* ... */ } // virtual allows to override
    virtual void doSomethingElse() = 0;      // pure virtual, no implementation
                                             // in base class

// to allow the derived class to access the adjacency list, it might be more
// meaningful to make it protected (but that depends on your specific needs)
protected:
    boost::adjacency_list<...> m_aList;
};

现在我们至少有一个纯虚函数(这不是必需的,在很多情况下,在基类中提供一个实现是没有意义的,但是,我们将把它留给派生类类来提供一个),我们创建了一个抽象类。抽象类不能被实例化(即你不能创建对象),只有非抽象派生类可以。

class SpecialWitness : public Witness
{
public:
    // you inherit already virtual destructor, so you don't need to specify
    // explicitly...

    void doSomething() override    // you CAN override, if this is meaningful
    { /* ... */ } 
    void doSomethingElse() override // if you don't override, the class will                                         
    { /* ... */ }                   // remain abstract (possible; if meaningful
                                    // is up to you to decide...) 
};

关于c++ - 如何让子类在 C++ 中返回一个不太通用的 typedef?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57327980/

相关文章:

c++ - sstream 不工作...(仍然)

c++ - dynamic_cast 中的模板推导

Java 表达式语言 : Interpolation?

c# - 当使用此类时,想要强制执行类的特定方法执行顺序。是否存在针对此的设计模式?

oop - 这个 OOP 惯例是真的吗?

c++ - 模板函数+仿函数参数,为什么仿函数没有内联?

c++ - 为 macOS arm64 arch 编译

c++ - 输出 LRESULT 到控制台

c++ - 从 Eclipse CDT 项目在 Linux 上编译后如何删除自动发现的路径?

javascript - 尝试在 Javascript 中获取 "classes"以发挥良好的作用