【问题标题】:Inheritance for class templates类模板的继承
【发布时间】:2018-11-18 12:06:13
【问题描述】:

我有三个类模板都使用相同的成员数据和相同方法的不同实例。

我想创建一个基类模板并让这三个继承它:

#include <vector>
#include <memory>

template <typename Sde>
class EulerFdm
{
private:
std::shared_ptr<Sde> sde;
int NT;
public:
std::vector<double> x;  // The mesh array
double  k;              // Mesh size

double dtSqrt;
public:
EulerFdm() = default;
EulerFdm(const std::shared_ptr<Sde>& stochasticEquation, int numSubdivisions)
    : sde(stochasticEquation), NT(numSubdivisions)
{

    NT = numSubdivisions;
    k = sde->Expiry() / static_cast<double>(NT);
    dtSqrt = std::sqrt(k);
    x = std::vector<double>(NT + 1);

    // Create the mesh array
    x[0] = 0.0;
    for (std::size_t n = 1; n < x.size(); ++n)
    {
        x[n] = x[n - 1] + k;
    }
}

double  advance(double  xn, double  tn, double  dt, double  normalVar, double  normalVar2) const
{
    return xn + sde->Drift(xn, tn) * dt + sde->Diffusion(xn, tn) * dtSqrt * normalVar;
}
};


template <typename Sde>
class EulerHeun
{
private:
    std::shared_ptr<Sde> sde;
    int NT;
public:
    std::vector<double> x;  // The mesh array
    double  k;              // Mesh size

    double dtSqrt;
public:
    EulerHeun() = default;
    EulerHeun(const std::shared_ptr<Sde>& stochasticEquation, int numSubdivisions)
        : sde(stochasticEquation), NT(numSubdivisions)
    {
        NT = numSubdivisions;
        k = sde->Expiry() / static_cast<double>(NT);
        dtSqrt = std::sqrt(k);
        x = std::vector<double>(NT + 1);

        // Create the mesh array
        x[0] = 0.0;
        for (std::size_t n = 1; n < x.size(); ++n)
        {
            x[n] = x[n - 1] + k;
        }
    }

double  advance(double  xn, double  tn, double  dt, double  normalVar, double  normalVar2) const
{
    auto a = sde->Drift(xn, tn);
    auto b = sde->Diffusion(xn, tn);
    auto suppValue = xn + a * dt + b * std::sqrt(dt) * normalVar;

    return xn + 0.5 * (sde->Drift(suppValue, tn) + a) * dt
        + 0.5 * (sde->Diffusion(suppValue, tn) + b) * std::sqrt(dt) * normalVar;
}
};

template <typename Sde>
class FdmFRKI
{
private:
std::shared_ptr<Sde> sde;
int NT;
public:
std::vector<double> x;  // The mesh array
double  k;              // Mesh size

double dtSqrt;
public:
FdmFRKI() = default;
FdmFRKI(const std::shared_ptr<Sde>& stochasticEquation, int numSubdivisions)
    : sde(stochasticEquation), NT(numSubdivisions)
{
    NT = numSubdivisions;
    k = sde->Expiry() / static_cast<double>(NT);
    dtSqrt = std::sqrt(k);
    x = std::vector<double>(NT + 1);

    // Create the mesh array
    x[0] = 0.0;
    for (std::size_t n = 1; n < x.size(); ++n)
    {
        x[n] = x[n - 1] + k;
    }
}

double  advance(double  xn, double  tn, double  dt, double  normalVar, double  normalVar2) const
{
    auto sqrk = std::sqrt(dt);
    auto Wincr = sqrk * normalVar;

    auto F1 = sde->Drift(xn, tn);
    auto G1 = sde->Diffusion(xn, tn);
    auto G2 = sde->Diffusion(xn + 0.5 * G1 * (Wincr - sqrk), tn);

    return xn + (F1 * dt + G2 * Wincr + (G2 - G1) * sqrk);
}
};

我尝试构建一个基类 FdmBase 如下:

template<typename Sde>
class FdmBase
{
protected:
       std::shared_ptr<Sde> sde;
       int NT;
public:
       std::vector<double> x;
       double k;
       double dtSqrt;
       FdmBase() = default;
       FdmBase(const std::shared_ptr<Sde>& stochasticEquation, int numSubdivision) : sde(stochasticEquation), NT(numSubdivisions)
{
    NT = numSubdivisions;
    k = sde->Expiry() / static_cast<double>(NT);
    dtSqrt = std::sqrt(k);
    x = std::vector<double>(NT + 1);

    // Create the mesh array
    x[0] = 0.0;
    for (std::size_t n = 1; n < x.size(); ++n)
    {
        x[n] = x[n - 1] + k;
    }
}
};

但是,当我删除派生类中的私有成员时,程序无法编译。

这就是我在 main() 方法中的调用方式:

auto fdm = std::shared_ptr<EulerFdm<Sde1>>(new EulerFdm<Sde1>(sde,NT));

【问题讨论】:

  • 错误信息是什么?
  • 它抱怨找不到数据。
  • 请包含一个 main() 函数并提供一个Compilable, Minimal, Complete, and Verifiable Example。这有助于我们帮助您。如果您可以在仍然创建故障的同时尽可能简化您的问题,这将有助于我们隔离使您的代码正常工作的问题。
  • 在编辑中我写下了我如何在 main() 中调用它。当不使用继承时,它可以工作。当我正式使用继承但保留派生类的所有实现时,它也有效。当我评论私人会员数据时,我收到一条错误消息。
  • 发布的代码中没有继承。发布演示问题的代码。如果您更改这个和那个并进行这个小调整并删除该行并以不同的顺序重新排列三个片段,那么将证明问题的代码没有帮助。阅读minimal reproducible example。

标签: c++ inheritance class-template


【解决方案1】:

您的模板继承可能存在两个不同的问题,具体取决于您调整模板以考虑继承的程度。

第一个潜在问题适用于所有类,包括非模板类:您只能在 mem-initializers 中使用基类构造函数和类的直接成员。所以你需要将sde和NT初始化移动到带有赋值的构造函数体中,或者让基类构造函数初始化它们。使用非模板基类,一切都会好起来的。

但是对于模板类,还有第二个问题related to the way in which name resolution is performed。这会导致在您的示例中找不到基本模板类的成员,并导致您描述的错误消息。这可以通过使成员在派生类中显式可见来解决,如下例所示:

template <typename T>
class B {
protected: 
    T a,b;  
public: 
    B() : a(10) 
    {
        b = a;  
    }
};
template <typename T> 
class C : public B<T> {
public: 
    using B<T>::b;   // Doesn't find these in the name resolution
    using B<T>::a;   // so just make them explicitly visible 
    C() //: a(20)
    {
        b = a +11; 
    }
};
int main() {
    C<double> x; 
    return 0;
 }

【讨论】:

  • 该问题仅包含EulerFdm、EulerHeun 和FdmFRKI 的继承前版本。你在哪里找到继承自FdmBase 的版本? (你的回答是合理的;我只是不知道如何验证它的准确性。)
  • @JaMiT 您可以使用 OP 提供的代码 sipper 自行尝试:获取完整的预继承代码,插入新的基类,然后通过将公共继承添加到基类,在初始类中删除基类中定义的成员。在每一步编译,因为有几个错别字。等等瞧!但这一切都归结为我在这里使用的更简单的情况,即Compilable, Minimal, Complete and Verifiable example
  • 好的,我试过了,我没能想出你提到的第一个问题(“只使用基类构造函数和mem-initializers中的类的直接成员”)。我想我失败的原因是我考虑添加一个基类初始化程序作为插入基类的一部分,并删除成员初始化程序作为删除成员的一部分。为什么假设OP没有做同样的事情? (也许将“模板继承中的问题”更改为“此模板继承中的潜在问题”?)
  • @JaMiT 好的,感谢您的建议。我已经编辑澄清
  • 感谢您的 cmets,它帮助我解决了问题。其实在构造派生类模板的时候需要调用基类模板构造函数EulerFdm(const std::shared_ptr&lt;Sde&gt;&amp; stochasticEquation, int numSubdivisions) : FdmBase&lt;Sde&gt;(stochasticEquation, numSubdivisions)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-05-23
  • 1970-01-01
  • 2018-01-18
  • 2011-03-22
  • 2012-10-05
相关资源
最近更新 更多