对于使用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),例如从同样的意义上讲,值得注意的是,您可以为虚拟函数提供默认实现-并非基类中的所有方法都必须是纯虚函数,甚至根本不需要是虚函数。

09-04 16:13
查看更多