对于使用C++编写大型程序包,我还比较陌生,因此对这种语言的某些OOP技术并不完全熟悉。
我正在编写可以运行模拟以在各种模型的框架内计算 Material 变形的代码。我有一个总体Sim
类,它具有set_boundary_conditions()
,update_grid()
,solve()
等方法。
我想将各种模型实现为派生类。例如,如果您只想考虑线性 flex 方程,可塑性的ElasticSim
等,我将拥有一个从Sim
派生的PlasticSim
类。
因为模型定义了必须解决的方程式,这些方程式已包含在update_grid()
函数中,所以我将update_grid()
变为virtual
,以便可以针对每个模型以不同的方式实现它。此外,set_boundary_conditions()
更加具体-给定模型中的不同模拟将具有不同的边界条件,因此virtual
和任何派生类中的Sim
都应为solve()
。将存在另一个派生类,该类实现给定物理情况的边界条件。
这可能过于复杂,但是我认为这是解决此问题的非常模块化且通用的方法。但是我离题了。我有一个主要问题。
首先,每种模型的Sim
方法都将相同。因此,我想在virtual
中定义它。但是,它调用Sim::update_grid()
函数,稍后将通过派生类实现这些函数。即,在伪代码和c++的混用中:
Sim::set_boundary_conditions()
for every time step...
Sim::update_grid()
在我可以实际测试之前,会有很多编码,而且我无法在线找到合适的答案。这真的有意义吗?特别是,尽管这些函数实际上将分别在派生类的派生类和派生类中实现,但我正在调用
Sim::set_boundary_conditions()
和ojit_code。 最佳答案
是的,这对于Sim::solve
是非虚拟的并调用虚拟函数是非常好的。构造函数和析构函数仅是必须注意虚拟调用的情况(因为vtable可能尚未完全形成或已被破坏)。
NVI(非虚拟接口(interface))在某个时候可能对您有用。这个想法包括对公共(public)接口(interface)使用非虚拟方法,对 protected /私有(private)方法使用虚拟方法。这个想法是允许中央控制,但仍然允许某些部分的可覆盖性。例:
class Foo
{
public:
virtual ~Foo() {}
// public non-virtual interface: calls virtual interface.
void do_something()
{
// Can add central stuff here that affects the
// entire hierarchy at any given time.
do_something_impl();
}
private:
// subclasses can override this part.
virtual void do_something_impl() = 0;
};
这种设计留出了摆动的空间,可以做一些集中适用于整个层次结构的事情(预见性或事后见解),同时允许子类部分覆盖行为并导致新的代码子分支。
但是,在基类中定义的,调用虚拟方法的中央
sim
方法具有的功能很好。那将使它成为一个混合了具体实现和可覆盖接口(interface)的抽象基类,而不是没有任何具体实现的纯虚拟接口(interface),例如从同样的意义上讲,值得注意的是,您可以为虚拟函数提供默认实现-并非基类中的所有方法都必须是纯虚函数,甚至根本不需要是虚函数。