c ++中的虚拟模板函数

Tou*_*dou 5 c++ polymorphism virtual templates function

我一直在寻找一种同时使用模板和多态的方法.这是我的问题的简化版本:

#include <iostream>
#include <vector>
using std::cout;
using std::endl;

//*******************************************************************
//*******************************************************************

struct DerivedStuff1
{
    static void eval() { cout << "evaluating DerivedStuff1" << endl; }
};

struct DerivedStuff2
{
    static void eval() { cout << "evaluating DerivedStuff2" << endl; }
};

//*******************************************************************
//*******************************************************************
class BaseClass
{
public:
    template<typename StuffType> virtual void eval() const = 0;
};

class DerivedClass1 : public BaseClass
{
public:
    template<typename StuffType> virtual void eval() const
    {
        std::cout << "We are in DerivedClass1: ";
        StuffType::eval();
    }
};

class DerivedClass2 : public BaseClass
{
public:
    template<typename StuffType> virtual void eval() const
    {
        std::cout << "We are in DerivedClass2: ";
        StuffType::eval();
    }
};

int main()
{
    BaseClass* c1 = new DerivedClass1;
    c1->eval<DerivedStuff1>();
    c1->eval<DerivedStuff2>();

    BaseClass* c2 = new DerivedClass2;
    c2->eval<DerivedStuff1>();
    c2->eval<DerivedStuff2>();

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

此代码无法编译,因为C++中不允许使用虚拟模板函数.我找到了一些解决这个问题的方法(CRTP等),但没有一个真正令人满意.有没有优雅的方法来解决这个问题?

n. *_* m. 7

访问者模式扭转了运行时多态性,并使运行时多态函数模板成为可能。除了模板化之外,它还有其他合法用途,所以我想你可以称它为有点优雅。

您的示例如下所示:

#include <iostream>

class DerivedStuff1 {
  public:
   static void eval() { std::cout << "Evaluating DerivedStuff1\n"; }
};

class DerivedStuff2 {
  public:
   static void eval() { std::cout << "Evaluating DerivedStuff2\n"; }
};

class DerivedClass1; class DerivedClass2;
class BaseClassVisitor {
  public:
    virtual void visit(DerivedClass1&) = 0;
    virtual void visit(DerivedClass2&) = 0;
};

class BaseClass {
  public:
    virtual void accept(BaseClassVisitor& v) = 0;
};

class DerivedClass1 : public BaseClass
{
  public:
    virtual void accept(BaseClassVisitor& v) { v.visit(*this); }
};

class DerivedClass2 : public BaseClass
{
  public:
    virtual void accept(BaseClassVisitor& v) { v.visit(*this); }
};


template <typename StuffType>
class EvalVisitor : public BaseClassVisitor
{
    virtual void visit(DerivedClass1&) {
        std::cout << "We are in DerivedClass1: ";
        StuffType::eval();
    }
    virtual void visit(DerivedClass2&) {
        std::cout << "We are in DerivedClass2: ";
        StuffType::eval();
    }

};

int main()
{
    EvalVisitor<DerivedStuff1> e1;
    EvalVisitor<DerivedStuff2> e2;

    BaseClass* c1 = new DerivedClass1;

    c1->accept(e1);
    c1->accept(e2);

    BaseClass* c2 = new DerivedClass2;

    c2->accept(e1);
    c2->accept(e2);

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

演示

当然,Visitor 的所有缺点都适用于此。


koc*_*ica 1

由于C++中不允许虚拟模板方法,因此您可以创建一个类模板并调用类模板参数的静态函数。

#include <iostream>
#include <vector>
using std::cout;
using std::endl;

//*******************************************************************
//*******************************************************************

struct DerivedStuff1
{
    static void eval() { cout << "evaluating DerivedStuff1" << endl; }
};

struct DerivedStuff2
{
    static void eval() { cout << "evaluating DerivedStuff2" << endl; }
};

//*******************************************************************
//*******************************************************************
class BaseClass
{
public:
    virtual void eval() const = 0;
};

template<typename StuffType>
class DerivedClass1 : public BaseClass
{
public:
    virtual void eval() const
    {
        std::cout << "We are in DerivedClass1: ";
        StuffType::eval();
    }
};

template<typename StuffType>
class DerivedClass2 : public BaseClass
{
public:
    virtual void eval() const
    {
        std::cout << "We are in DerivedClass2: ";
        StuffType::eval();
    }
};

int main()
{
    BaseClass* c1 = new DerivedClass1<DerivedStuff1>;
    c1->eval();
    c1 = new DerivedClass1<DerivedStuff2>;
    c1->eval();

    BaseClass* c2 = new DerivedClass2<DerivedStuff1>;
    c2->eval();
    c2 = new DerivedClass2<DerivedStuff2>;
    c2->eval();

    // deletes

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

输出

We are in DerivedClass1: evaluating DerivedStuff1
We are in DerivedClass1: evaluating DerivedStuff2
We are in DerivedClass2: evaluating DerivedStuff1
We are in DerivedClass2: evaluating DerivedStuff2
Run Code Online (Sandbox Code Playgroud)