C++ 中的构造函数可以是抽象的吗?
Can a constructor be abstract in C++?
我有一些对象排列,它们的相互关系(一种拓扑)与对象的类型无关。我想对来自同一容器 class 的不同包含的 classes、subclass 使用相同的结构和相互关系。
在我的容器 class 中,只要知道所包含的 classes 包含在网格中,就可以充分描述关系;毫无疑问,网格是否已填充。也就是说,从容器派生的 classes 必须首先在它们的构造函数中填充网格,然后它们就可以开始了。
也就是说,我可以使用一个空容器,如果派生的 classes 在其构造函数中使用相应的对象填充网格,则一切正常。但是,构造函数必须填充网格以提供合理的功能。如果它不是构造函数,我会将其抽象化。
我可以将它留空,让职责在 subclasses 中填充它,或者我可以将 Populate() 方法作为抽象方法,但应该从构造函数中调用它。
哪种(或哪种其他)方法最好?
构造函数不能是虚拟的。
在基的构造函数中调用虚方法是有问题的,因为派生对象还不存在。
您可以改为提供一个工厂函数,在构造对象后调用 populate
。
class Base
{
template <typename Derived, typename... Args>
static Derived make(Args&&... args)
{
Derived result(std::forward<Args>(args)...);
result.populate();
return result;
}
protected:
Base() = default;
virtual void populate() = 0;
};
你问题的关键部分是:
However, the constructor must populate the grid to provide a reasonable functionality.
这是所有子类的必要后置条件。不幸的是,没有办法强制 unit-testing 每个 ctor 确认它确实做了你想要的。
委托任何形式的延迟调度并要求通过抽象成员函数实现实际上并不能绕过这个问题。当然,这可能会使 "forget" 更难满足后置条件,但您仍然需要为此编写单元测试,因此实际上您一无所获。
在 C++ 中执行任何操作的唯一方法是请求一个值。您需要隐藏默认构造函数,并公开静态工厂成员函数 return 例如pair<ObjectConstructed, GridFootprint>
。然后你可以在 GridFootprint
构造函数上强制执行 non-emptiness。
这种方法会很有效,但它需要打破对象和网格之间隐藏的依赖关系。这可能是一件好事,但如果没有看到整个问题就很难说。
我有一些对象排列,它们的相互关系(一种拓扑)与对象的类型无关。我想对来自同一容器 class 的不同包含的 classes、subclass 使用相同的结构和相互关系。 在我的容器 class 中,只要知道所包含的 classes 包含在网格中,就可以充分描述关系;毫无疑问,网格是否已填充。也就是说,从容器派生的 classes 必须首先在它们的构造函数中填充网格,然后它们就可以开始了。 也就是说,我可以使用一个空容器,如果派生的 classes 在其构造函数中使用相应的对象填充网格,则一切正常。但是,构造函数必须填充网格以提供合理的功能。如果它不是构造函数,我会将其抽象化。 我可以将它留空,让职责在 subclasses 中填充它,或者我可以将 Populate() 方法作为抽象方法,但应该从构造函数中调用它。 哪种(或哪种其他)方法最好?
构造函数不能是虚拟的。
在基的构造函数中调用虚方法是有问题的,因为派生对象还不存在。
您可以改为提供一个工厂函数,在构造对象后调用 populate
。
class Base
{
template <typename Derived, typename... Args>
static Derived make(Args&&... args)
{
Derived result(std::forward<Args>(args)...);
result.populate();
return result;
}
protected:
Base() = default;
virtual void populate() = 0;
};
你问题的关键部分是:
However, the constructor must populate the grid to provide a reasonable functionality.
这是所有子类的必要后置条件。不幸的是,没有办法强制 unit-testing 每个 ctor 确认它确实做了你想要的。
委托任何形式的延迟调度并要求通过抽象成员函数实现实际上并不能绕过这个问题。当然,这可能会使 "forget" 更难满足后置条件,但您仍然需要为此编写单元测试,因此实际上您一无所获。
在 C++ 中执行任何操作的唯一方法是请求一个值。您需要隐藏默认构造函数,并公开静态工厂成员函数 return 例如pair<ObjectConstructed, GridFootprint>
。然后你可以在 GridFootprint
构造函数上强制执行 non-emptiness。
这种方法会很有效,但它需要打破对象和网格之间隐藏的依赖关系。这可能是一件好事,但如果没有看到整个问题就很难说。