如何模拟涉及成员函数和派生类的调用

时间:2015-09-07 13:57:06

标签: c++ templates

我有一个封装在类中的状态机。这是通过依次调用一系列成员函数来完成这些操作来完成的。我也有几个派生类,我想对它们做同样的序列。有没有办法模板化这段代码?

#include <iostream>

class MyClass {
    std::string name;
public:
    typedef void (MyClass::*Function)(std::ostream &ostr);
    void Func1(std::ostream &ostr) { ostr << "F1" << name << std::endl; };
    void Func2(std::ostream &ostr) { ostr << "F2" << std::endl; };
    static Function printers[];
    void Print(std::ostream &ostr);
};

MyClass::Function MyClass::printers[] = {
    &MyClass::Func1,
    &MyClass::Func2,
    NULL
};

void MyClass::Print(std::ostream &ostr)
{
    // various stuff to do before
    // ...
    int i = 0;
    for (Function *fp = printers; *fp; fp++, i++) {
        std::cerr << "Calling function " << i << std::endl;
        ((this)->*(*fp))(ostr);
        std::cerr << "Called function " << i << std::endl;
    }
    // other stuff here...
}

class DerClass: public MyClass {
    int index;
public:
    typedef void (DerClass::*Function)(std::ostream &ostr);
    void Func3(std::ostream &ostr) { ostr << "F3" << index << std::endl; };
    static Function printers[];
    void Print(std::ostream &ostr);
};

DerClass::Function DerClass::printers[] = {
    &DerClass::Func1,
    &DerClass::Func3,
    NULL
};

// I'd rather not repeat all this stuff, can I template it??
void DerClass::Print(std::ostream &ostr)
{
    // various stuff to do before
    // ...
    int i = 0;
    for (Function *fp = printers; *fp; fp++, i++) {
        std::cerr << "Calling function " << i << std::endl;
        ((this)->*(*fp))(ostr);
        std::cerr << "Called function " << i << std::endl;
    }
    // other stuff here...
}

int main()
{
    MyClass cl1;
    cl1.Print(std::cout);
    DerClass cl2;
    cl2.Print(std::cout);
}

代码运行并且有效,但是我只想编写一次Print例程,而不是每个新类,有没有办法做到这一点,模板?其他课程?

我希望像

这样的东西
template <class T>
void T::Print(std::ostream &str) {
    int i = 0;
    for (Function *fp = printers; *fp; fp++, i++) {
    std::cerr << "Calling function " << i << std::endl;
    ((this)->*(*fp))(ostr);
    std::cerr << "Called function " << i << std::endl;
    }
}

虽然没有编译。

  

错误:无效使用模板类型参数'T'void   T :: Print(std :: ostream&amp; str){

2 个答案:

答案 0 :(得分:0)

我宁愿把它写成评论,但代码的数量根本不可读。

您可以在下面找到有关如何继承&#34;的可能解决方案。你的Print

这应该仅作为建议或提示。特别是printers的初始化并没有真正完成&#34;一种好的方式&#34;。

希望它能帮助你

#include <iostream>
#include <string>


template <class Derived>
class MyClass {

    std::string name;

protected:
    typedef void (Derived::*Function)(std::ostream &ostr);
    Function* printers;

public:
    MyClass() 
        :printers(nullptr)
    {
    }

    ~MyClass()
    {
        delete[] printers;
    }

    virtual void initPrinters()
    {
        if (printers == nullptr)
        {
            printers = new Function[3];
            printers[0] = &MyClass<Derived>::Func1;
            printers[1] = &MyClass<Derived>::Func2;
            printers[2] = NULL;
        }
    }

    void destroyPrinters()
    {
        if (printers != nullptr)
        {
            delete[] printers;
        }
    }

    void Print(std::ostream &ostr)
    {
        initPrinters();
        // various stuff to do before
        // ...
        int i = 0;
        for (Function *fp = printers; *fp; fp++, i++) {
            std::cerr << "Calling function " << i << std::endl;
            (((Derived*)this)->*(*fp))(ostr);
            std::cerr << "Called function " << i << std::endl;
        }
        // other stuff here...
    }

    void Func1(std::ostream &ostr) { ostr << "F1" << name << std::endl; };
    void Func2(std::ostream &ostr) { ostr << "F2" << std::endl; };
};

template <>
class MyClass<void> : public MyClass<MyClass<void>>
{
};

class DerClass : public MyClass<DerClass> {
    int index;

public:

    virtual void initPrinters() override
    {
        if (printers == nullptr)
        {
            printers = new Function[3];
            printers[0] = &DerClass::Func1;
            printers[1] = &DerClass::Func3;
            printers[2] = NULL;
        }
    }

    void Func3(std::ostream &ostr) { ostr << "F3" << index << std::endl; };
};

int main()
{
    MyClass<void> cl1;
    cl1.Print(std::cout);
    DerClass cl2;
    cl2.Print(std::cout);
}

编辑:第二种方法

在我看来,这个更漂亮。此外,代码更少,编译器可以对其进行优化:

#include <iostream>
#include <string>


class MyClass {

    std::string name;

protected:


    template <class T>
    void print(std::ostream &ostr, void(T::*printFunc)(std::ostream&))
    {
        (((T*)this)->*printFunc)(ostr);
    }

    template <class T, typename... PrintFunctions>
    void print(std::ostream &ostr, void(T::*printFunc)(std::ostream&), PrintFunctions... printFuncs)
    {
        (((T*)this)->*printFunc)(ostr);
        print(ostr, printFuncs...);
    }

public:

    virtual void Print(std::ostream &ostr)
    {
        print(ostr, &MyClass::Func1, &MyClass::Func2);
    }

    void Func1(std::ostream &ostr) { ostr << "F1" << name << std::endl; };
    void Func2(std::ostream &ostr) { ostr << "F2" << std::endl; };
};

class DerClass : public MyClass {
    int index;

public:
    virtual void Print(std::ostream &ostr) override
    {
        print(ostr, &DerClass::Func1, &DerClass::Func3);
    }

    void Func3(std::ostream &ostr) { ostr << "F3" << index << std::endl; };
};

int main()
{
    MyClass cl1;
    cl1.Print(std::cout);
    DerClass cl2;
    cl2.Print(std::cout);
}

答案 1 :(得分:0)

如果&#34;各种东西&#34;和其他东西&#34;不同的是,你可以将这些部分虚拟化。

但是你不能在基类中调用子类的成员函数,所有函数都需要具有相同的类型。

一个建议可能是间接通过自由职能。

class MyClass;
typedef void (*Printer)(MyClass*, std::ostream&);

class MyClass {
    std::string name;
public:
    MyClass();
    void Func1(std::ostream &ostr) { ostr << "F1" << name << std::endl; };
    void Func2(std::ostream &ostr) { ostr << "F2" << std::endl; };
    void Print(std::ostream &ostr);
protected:
    MyClass(Printer* ps) : myprinters(ps) {}
    virtual void PrePrint() { /* Various stuff... */ }
    virtual void PostPrint() { /* Other stuff... */ }
private:
    Printer* myprinters;

};

void MyFunc1(MyClass* obj, std::ostream& os) { obj->Func1(os); }
void MyFunc2(MyClass* obj, std::ostream& os) { obj->Func2(os); }

Printer myclassprinters[] = {
    &MyFunc1,
    &MyFunc2,
    NULL
};

MyClass::MyClass()
    : myprinters(myclassprinters)
{

}

void MyClass::Print(std::ostream &ostr)
{
    PrePrint();
    int i = 0;
    for (Printer *fp = myprinters; *fp; fp++, i++) {
        std::cerr << "Calling function " << i << std::endl;
        (*fp)(this, ostr);
        std::cerr << "Called function " << i << std::endl;
    }
    PostPrint();
}

class DerClass: public MyClass {
public:
    DerClass();
    void Func3(std::ostream &ostr) { ostr << "F3" << index << std::endl; };
protected:
    void PrePrint() { /* More stuff... */ }
};

// C-cast for conciseness only. Use something safer in the real world.
void DerFunc(MyClass* obj, std::ostream& ostr) { ((DerClass*)obj)->Func3(ostr); }

Printer derclassprinters[] = {
    &MyFunc1,
    &DerFunc,
    NULL
};

DerClass::DerClass()
    : MyClass(derclassprinters)
{

}

这为每个实例使用指针成员 - 我假设你不想为每个实例存储整个函数表。