Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/143.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ C++;。模板和运行时用户信息_C++_Templates_Polymorphism_Numerical Integration - Fatal编程技术网

C++ C++;。模板和运行时用户信息

C++ C++;。模板和运行时用户信息,c++,templates,polymorphism,numerical-integration,C++,Templates,Polymorphism,Numerical Integration,我一直在努力学习更多关于泛型编程的知识,因为我认为我对它了解得还不够。所以我在考虑如何实现我的一个程序的模板版本。 我尝试使用的程序是一个数字积分器程序,用户在其中选择要使用的积分器(即Euler、Runge-Kutta等),然后集成他们选择的任何函数。 我目前的方法是使用一个名为Integrator的抽象基类和几个实现集成方法的派生类。 因此,代码看起来是这样的(更多内容正在进行,但这只是为了展示方法)。请注意,我使用Qt进行此操作,并声明一个Integrator*Integrator;在主窗

我一直在努力学习更多关于泛型编程的知识,因为我认为我对它了解得还不够。所以我在考虑如何实现我的一个程序的模板版本。 我尝试使用的程序是一个数字积分器程序,用户在其中选择要使用的积分器(即Euler、Runge-Kutta等),然后集成他们选择的任何函数。 我目前的方法是使用一个名为Integrator的抽象基类和几个实现集成方法的派生类。 因此,代码看起来是这样的(更多内容正在进行,但这只是为了展示方法)。请注意,我使用Qt进行此操作,并声明一个Integrator*Integrator;在主窗口类中

void MainWindow::on_integrateButton_clicked() {
string whichIntegrator = getUserChoice();

integrator = getIntegrator( whichIntegrator, whichFunction, order );
integrator->setUp( data ); // things like initial conditions, time, step size, etc...

runIntegratorInNewThread();
}
使用getIntegrator时,基本上使用工厂方法

// x being current data, xdot being the results of evaluating derivatives
typedef void (*pFunction)(const double t, const double x[], double *xdot);

Integrator* getIntegrator( const string &whichIntegrator, pFunction whichFunction, int order  ) {
    if (whichIntegrator == "Euler") {
        return new Euler(whichFunction, order);
    } else if (whichIntegrator == "RungeKutta") {
        return new RungeKutta(whichFunction, order);
    }
}

因此,该方法工作良好,积分器程序运行良好。现在我知道模板函数是在编译时生成的,并且假设我使用的是运行时信息,那么您将如何使用模板实现这一点?如果问题不清楚,我要问的是。。。如果用户在运行时选择使用哪种集成器,那么如何使用模板方法调用正确的集成函数?

模板不是万能的,尽管您可以用它们做很多事情,但不要低估您当前使用的多态性的威力

这可以通过模板实现吗?答案是肯定的,使用C++11和shared_ptr看起来是这样的:

template<class T>
std::shared_ptr<T> getIntegrator(pFunction whichFunction, int order)
{
    return std::make_shared<T>(whichFunction, order);
}
模板
std::shared_ptr getIntegrator(pFunction whichFunction,int order)
{
return std::make_shared(whichFunction,order);
}
在您的来电者中:

std::shared_ptr<Integrator> integrator;
if (whichIntegrator  == "Euler")
{
    integrator = getIntegrator<Euler>(whichFunction, order);
}
else if(whichIntegrator  == "RungeKutta")
{
    integrator = getIntegrator<RungeKutta>(whichFunction, order);
}
std::共享ptr积分器;
if(whichIntegrator==“Euler”)
{
integrator=getIntegrator(函数,顺序);
}
else if(whichIntegrator==“RungeKutta”)
{
integrator=getIntegrator(函数,顺序);
}
另一个注意事项是,在这里,你应该非常小心内存泄漏,你正在更新和对象,如果你从未释放它,你将有一个泄漏

尽管如此,我希望这个答案表明,虽然您可以使用模板,但我不推荐在这种情况下使用,多态性在这里工作得很好。
这个例子只是展示了模板的作用,在一个非常简单和冗余的情况下

假设我想用静态类型的积分器编写整个系统

我会在单击集成按钮时将您的
,并将其更改为如下内容:

void MainWindow::on_integrateButton_clicked() {
  string whichIntegrator = getUserChoice();

  runInNewThread( [whichIntegrator,whichFunction,order]() {
    struct functor {
      FunctionType func;
      OrderType order;
      functor( FunctionType func_in, OrderType order_in):func(std::move(func_in)), order(std::move(order_in)) {}
      template<typename Integrator>
      void operator()( Integrator* integrator ) {
        // code using integrator here, not a virtual interface to it, an actual instance of the final type
      }
    };
    RunWithChosenIntegrator( whichIntegrator, functor(whichFunction,order) );
  } );
}
template<typename Functor>
void RunWithChosenIntegrator( std::string const&whichIntegrator, Functor&& func ) {
  if (whichIntegrator == "bob") {
    BobIntegrator bob;
    func( &bob );
  } else if (whichIntegrator == "alice" ) {
    AliceIntegrator alice;
    func( &alice ):
  }
}
如您所见,我们根据
whichIntegrator
参数使用不同类型的对象调用
func
。您甚至可以使用元编程生成
if
/
else if
链,这些方法都很有趣,但在您更熟悉基本模板编程之前,可能不值得学习

Functor
func
需要能够接受指向我们调用它的任何类型和所有类型的指针。一个简单的例子可能是一个
func
,它只需要一个指向基类的指针,而我上面给出的例子则需要一个
T*
模板类型

只有当运行时多态性的开销太高,或者您实际上需要以非统一的方式与不同的集成器类交互,而这种方式很难或不可能通过运行时多态性来捕获时,所有这些才有价值


我怀疑这里的情况是否如此。

这怎么可能
哪个
应该指示分配哪个积分器。那么你必须明确指出的
T
是什么呢?另外,我同意这里不应该使用模板,但他问他们是否可以,我举了一个例子。然后答案应该是“不要在这里使用模板”.
getIntegrator
make_shared
完全相同。我决定对这个答案投赞成票,因为它对我来说最有意义,就像我所想的那样。不要试图将模板应用于随机情况。它们在某些场景中非常有用,但我不认为这是其中之一。只要使用虚拟函数保持动态多态性就行了。谢谢你的回复。我想这是因为我看到了一些积分器代码,都使用了模板。与他们不同的是,它更像是一个“打开cpp文件并在那里编辑内容以运行它”,而我的GUI有各种各样的提示。我只是想看看这是否可以模板化。我目前使用的模板扩展到为容器编写算法,我相信我可以使用它们做更多的事情。集成毕竟是一种算法,所以也许我可以将它模板化。不过,这里最好还是使用虚拟函数。谢谢你的回答,这里有很多内容要看,特别是我还没有实际使用的右值引用的使用。