【问题标题】:Overriding multiple inherited templated functions with specialized versions用专门的版本覆盖多个继承的模板函数
【发布时间】:2010-12-26 05:49:10
【问题描述】:

好的,先上示例代码;这是我试图传达我正在尝试做的事情的尝试,尽管它没有编译:

#include <iostream>

template <class T>
class Base
{
public:
    virtual void my_callback() = 0;
};

class Derived1
    : public Base<int>
    , public Base<float>
{
public:
    void my_callback<int>()
    {
        cout << "Int callback for Derived1.\n";
    }
    void my_callback<float>()
    {
        cout << "Float callback for Derived\n";
    }
};

class Derived2
    : public Base<int>
    , public Base<float>
{

public:
    void my_callback<int>()
    {
        cout << "Int callback for Derived2.\n";
    }
    void my_callback<float>()
    {
        cout << "Float callback for Derived2\n";
    }

};

int main()
{
    {
        Derived1 d;
        Base<int> * i_p = d;
        Base<float> * i_f = d;

        i_p->my_callback();
        i_f->my_callback();
    }
    {
        Derived2 d;
        Base<int> * i_p = d;
        Base<float> * i_f = d;

        i_p->my_callback();
        i_f->my_callback();
    }

    //Desired output:
    // Int callback for Derived1.
    // Float callback for Derived1
    // Int callback for Derived2.
    // Float callback for Derived2
    system("Pause");
}

所以,我要做的是创建一种封装类来继承,它会自动将派生类连接到各种回调列表;它需要将派生类的特定实例连接到列表,并且我希望“用户”拥有/获取将回调函数作为创建派生类的一部分,如您所见。

看起来这应该可以工作,尽管我可能需要使用不同的语法。如果不行,有什么建议吗?

【问题讨论】:

标签: c++ templates overriding multiple-inheritance specialization


【解决方案1】:

是的,你可以做到这一点:

#include <iostream>
using namespace std;

template <class T>
class Base
{
public:
  virtual void my_callback() = 0;
};

class Derived1 : public Base<int>, public Base<float>
{
public:
  void Base<int>::my_callback() {
    cout << "Int callback for Derived1.\n";
  }
  void Base<float>::my_callback() {
    cout << "Float callback for Derived\n";
  }
};

class Derived2 : public Base<int>, public Base<float>
{
public:
  void Base<int>::my_callback() {
    cout << "Int callback for Derived2.\n";
  }
  void Base<float>::my_callback() {
    cout << "Float callback for Derived2\n";
  }
};

int main()
{
  {
    Derived1 d;
    Base<int> * i_p = &d;
    Base<float> * i_f = &d;
    i_p->my_callback();
    i_f->my_callback();
  }
  {
    Derived2 d;
    Base<int> * i_p = &d;
    Base<float> * i_f = &d;
    i_p->my_callback();
    i_f->my_callback();
  }
}

输出:

Int callback for Derived1.
Float callback for Derived
Int callback for Derived2.
Float callback for Derived2

【讨论】:

  • 这不会编译 (gcc)。你的 Derived::my_callback 声明不能这样工作。
  • 这对我有用;值得注意的是,我使用的是 Visual Studio 2008,我知道它有一些不标准的功能。谢谢!
  • 是的,这是支持显式接口实现的副作用。只要你能坚持使用 MSVC,你会没事的。
  • 谢谢,但它希望有标准的方式来做到这一点。仍在考虑如何以标准方式完成这项工作。
【解决方案2】:

你想要的是不可能

您可以添加模板特化,但我不知道这是否真的有帮助:

template <class T>
class Base {
public:
  virtual void my_callback() = 0;
};

template <>
class Base<int> {
public:
  virtual void my_callback() {
    cout << "Base<int>::my_callback()\n";
  }
};

template <>
class Base<float> {
public:
  virtual void my_callback() {
    cout << "Base<float>::my_callback()\n";
  }
};

class Derived1 : public Base<int>, public Base<float> {
public:
  // NOTE: no my_callback() implementation here
};

class Derived2 : public Base<int>, public Base<float> {
public:
  virtual void my_callback() {
    cout << "Derived2::my_callback()\n";
  }
};


int main()
{
  {
    Derived1 d;
    Base<int> * i_p = &d;
    Base<float> * i_f = &d;
    i_p->my_callback();
    i_f->my_callback();
  }
  {
    Derived2 d;
    Base<int> * i_p = &d;
    Base<float> * i_f = &d;
    i_p->my_callback();
    i_f->my_callback();
  }
}

输出:

Base<int>::my_callback()
Base<float>::my_callback()
Derived2::my_callback()
Derived2::my_callback()

让我试着解释一下原因:

Derived1 d;
Base<int> * i_p = &d;
Base<float> * i_f = &d;

// will check the vtable, and will call
//  either Derived1::my_callback
//  OR Base<int>::my_callback
i_p->my_callback();

// will check the vtable, and will call
//  either Derived1::my_callback
//  OR Base<float>::my_callback
i_f->my_callback();

虽然通过 vtable 在 Derived1 类中有两个版本的 my_callback(),但您不能覆盖其中任何一个,您只能同时覆盖两个版本(就像示例中的 Derived2 所做的那样)!

您应该只提供两个方法“my_callback1()”和“my_callback2()”。

【讨论】:

    【解决方案3】:

    template 相关的 virtuality 不会在你的脑海中引起警觉吗? ;)

    你必须选择你的立场,要么是静态的,要么是动态的。

    【讨论】:

    • "与模板关联的虚拟性不会在您的脑海中引发警报吗?" 为什么会这样?
    【解决方案4】:

    无论是使用模板类还是非模板类,都可以通过使用this stylethis one 中的帮助类来完成。

    (如果您不打算使用 Microsoft 特定的限定名称,这似乎是唯一可移植的解决方案。)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-01-10
      • 1970-01-01
      • 2012-05-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多