基类中使用 this 指针的模板函数

Posted

技术标签:

【中文标题】基类中使用 this 指针的模板函数【英文标题】:Template function in base class using this-pointer 【发布时间】:2014-04-21 21:12:39 【问题描述】:

考虑以下代码:

struct Base

    ~Base() 
    virtual double operator()(double x) const = 0;
;

template<typename F, typename G> struct Compose;  //forward declaration of Compose

struct Derived1 : public Base    //plus many more derived classes

    virtual double operator()(double x) const return x;
    template <typename F>
    Compose<Derived1,F> operator()(const F& f) const return Compose<Derived1,F>(*this,f);
;

template<typename F, typename G>
struct Compose : public Base

     Compose(const F &_f, const G &_g) : f(_f), g(_g) 
     F f;
     G g;
     virtual double operator()(double x) const return f(g(x));
;

void test()

    Derived1 f,g;
    auto h=f(g);

这里的 compose 类接受两个派生类 f,g 并通过 operator() 返回组合 f(g(x))。

是否有可能避免在许多派生类中的每一个中显式定义,并在基类中添加一个函数?


编辑:为了更好地解释我在寻找什么:原则上,我想在基类中添加如下内容

template<typename F> Compose<decltype(*this), F>
operator()(const F& f) return Compose<decltype(*this), F>(*this,f);

我尝试了这个,希望 decltype(*this) 自动插入派生类的类型。但它似乎不像这样工作......


解决方案:我终于找到了办法,那就是通过CRTP。然后 Base 类采用以下形式

template<typename Derived>
struct Base

    ~Base() 
    virtual double operator()(double x) const = 0;

    template<typename F> Compose<Derived, F>
    operator()(const F& f) return Compose<Derived, F>(static_cast<Derived const&>(*this),f);
;

派生类是从

struct Derived1 : public Base<Derived1>

【问题讨论】:

如果我们从 编译 的代码开始,但并没有达到您想要的效果,那将会很有帮助。第一个来源在这方面失败了(出于多种原因),第二个来源也是如此,因此很难进入这个问题,更不用说小马可行的替代方案了。 (并且Compose 不是一个函数;它看起来像一个模板类,但目前甚至不是那个)。 你是对的。我会在几分钟内更新它(这里和那里几个逗号;-))。 完成。在 MSVC 11 中编译。 不作为答案包含在内,因为它与您似乎正在寻找的虚拟模型剥离,但您也可以考虑使用 CRTP 作为选项的静态多态性 (See it live)。这可能会让你大吃一惊。 【参考方案1】:

鉴于您的Base 是纯虚拟的,因此可以将模板功能移至Base。无论如何,所有派生类都必须实现double operator()(double x) 并委托。

我还使用了Base 指针而不是实例,因为正如您指出的那样,否则它在Compose 结构中不起作用(可能想要更改那里的实现以使其不易泄漏......)。

请注意,我从您的层次结构中取出了Compose(看起来它可以用于更通用的目的) - 随时将它放回原处(它将允许无休止的组合)。

我还删除了所有 const,因为 struct 需要为 const 对象提供默认 CTOR(随意放入它们)。

我重命名了组合运算符,因为我的编译器被客户端代码中的另一个 operator() 蒙蔽了双眼。

它需要清理的核心在那里:

template <typename F, typename G> struct Compose

     Compose( F* _f,  G &_g) : f(_f), g(_g) 
      F* f;
     G g;
     double operator()(double x)  return (*f)(g(x));
;

struct Base

    ~Base() 
    virtual double operator()(double x) = 0;
    template <typename F> Compose<Base,F> composeMeWith(F& f)  return Compose<Base,F>(this,f);    
;

struct D1 : public Base 

    virtual double operator()(double x)   return 1.0; 
;

struct D2 : public Base 

    virtual double operator()(double x)   return 2.0; 
;

一些客户端代码:

#include <iostream>
using namespace std;

int main(int argc, char** argv) 

     D1 d1;
     D2 d2;

    auto ret1 = d1.composeMeWith(d2);
    auto ret2 = d2.composeMeWith(d1);

    cout << ret1(100.0) << endl;
    cout << ret2(100.0) << endl;

【讨论】:

非常感谢!核心很重要,其余的(shared_ptr 或其他)都是微不足道的。我明天会测试它并接受(--希望 :-D)。 再次感谢,您提出的解决方案将起作用。但我很好奇是否有任何替代“指针”方法的方法?我的意思是这个任务听起来并不难:派生类只需要插入它自己的类型模板参数(这是我尝试使用 decltype(*this)...)。这是否可能仅使用基类中定义的函数? 我认为您不能在模板类型名称中引用this(当时没有this)。不过,您可以在 中使用它。值得调查。 @davidhigh decltype 的想法不起作用的原因在这里:***.com/questions/10424337/…【参考方案2】:

您的 Base 类是纯抽象的,因此您不能这样做。您可以将Base 类定义为具体类,然后在具体Base 类中定义重载函数调用运算符。请看下面的代码:

struct Base

    ~Base() 
    virtual double operator()(double x) const return x;
;

struct Derived1 : public Base    //plus many more derived classes


;

int main()

  Derived1 d;
  double x = d(1);
  std::cout << x << std::endl;

  return 0;

【讨论】:

嗯...谢谢,但这是微不足道的。我已经编辑了我的问题,以便更清楚我想要什么。

以上是关于基类中使用 this 指针的模板函数的主要内容,如果未能解决你的问题,请参考以下文章

在派生类中使用模板基类模板构造函数

虚函数和基类中的this指针的问题!

模板化函数或带有指向基类的指针的函数

派生类中隐藏的基类模板成员函数,尽管参数列表不同

指向基类中成员函数的指针数组

基类的函数指针指向子类的成员函数?