开发者

Overriding multiple inherited templated functions with specialized versions

开发者 https://www.devze.com 2022-12-14 09:32 出处:网络
Okay, sample code first; this is my attempt at communicating what it is that I\'m trying to do, although it doesn\'t compile:

Okay, sample code first; this is my attempt at communicating what it is that I'm trying to do, although it doesn't compile:

#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>
   开发者_如何学JAVA , 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");
}

So, what I'm trying to do is to make a sort of wrapper class to inherit from that will automatically connect the derived class to various callback lists; it needs to connect a specific instance of the derived class to the list, and I want the "user" to have / get to make the callback functions as part of making the derived class, as you can see.

It seems like this should be able to work, although I may need to use a different syntax. If it can't work, do you have any suggestions?


Yes, you can make this work:

#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();
  }
}

Output:

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


What you want is not possible.

You could add template specializations, though I do not know if this really helps:

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();
  }
}

Output:

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

Let me try to explain why:

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();

Though through the vtable there are two versions of my_callback() in class Derived1, you CAN NOT override either of them, you can only override both at once (like Derived2 does in the example)!

You should just provide two methods "my_callback1()" and "my_callback2()".


Whether using a template class or a non-template one, this can be done by using helper classes in this style or this one.

(It seems this is the only portable solution if you do not plan to use Microsoft specific qualified names.)


Doesn't virtuality associated with template raises an alarm in your head ? ;)

You have to choose your side, either the static, or the dynamic one.

0

精彩评论

暂无评论...
验证码 换一张
取 消