免责声明:我明白以下可能不是正确的做事方式,并希望就我如何正确做事提出建议。
我有以下 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
。因此,SpecialSolver
中 solve()
的实现应该如下所示。
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 : VertexProperties
和 SpecialGraphProperties : 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/