使用没有虚拟的模板从基类调用派生类函数

时间:2013-12-16 14:15:22

标签: c++ templates

我需要使用脚本生成类的一些成员/方法。我试图将这个类拆分为两个,基类是生成成员,派生类有手动编码成员。但是,我陷入困境,想弄清楚如何从基类D::f2()调用派生成员函数B::f1()

以下是简化代码:

#include <cstdio>

template <typename _T>
class B { 
public:
    void f3() {
        puts("okay");
    }
    void f1() {   
        f2();   // What C++ Magic to call f2() properly !!!
    }
};

class D : public B<D> {
public:
    void f2() {
        f3();
    }

};

int main() {
    D d;
    d.f1();
}

有什么办法,我可以在不使用虚函数的情况下从D::f2()拨打B::f1()吗?

稍后添加:

如果我们进行指针操作,我们最终会注射,我明白这不是一个好主意,我会采取不做的建议。让我们停止那个线程。

我正在尝试仅使用模板找到解决方案。我可以生成任何复杂的东西 为生成的代码。它甚至可以是几个仿函数等。但是手工编码 书面部分应该是可手工编码的。

5 个答案:

答案 0 :(得分:5)

如果你真的真的想要这样做:

static_cast<_T*>(this)->f2();

正如人们所提到的,这是一个奇怪的模板模板!

答案 1 :(得分:0)

基类不应该有它的孩子的概念。尝试从基类调用子方法是一个糟糕的架构的可靠迹象。顺便说一下,虚拟功能对你没有帮助。

如果您必须从基类调用子函数,您可以像在代码中的任何其他函数那样调用子函数。仍然需要一个基类实例来调用它,或者你需要static_cast指向子类类型指针的this指针。这是一个非常糟糕的主意!

答案 2 :(得分:0)

这是典型的Curiously recuring template pattern。你可以这样做:

template <typename _T>
class B { 
public:
     void f3() {
      puts("okay");
     }
     void f1() {      
      static_cast<_T>(this)->f2();
     }

};

答案 3 :(得分:0)

答案 4 :(得分:0)

还有另一种方式,但代价是丑陋的C风格/重新诠释:

#include <cstdio>
#include <functional>


class B { 
public:
    typedef std::function<void (B*)> Function;    

    void f3() {
        puts("okay");
    }
    void f1() {   
        _func(this);
    }

    Function _func;
};

class D : public B 
{
public:
    D()
    {
        _func = (void (B::*)()) &D::f2; // Here is the awfull cast I hate to do
    }

    void f2() {
        f3();
    }

};

int main() {
    D d;
    d.f1();
}

http://ideone.com/yOR0xT

我觉得这比CRTP要干净得多,因为你没有编译时检查......