4

Хорошо, сначала пример кода; это моя попытка общения, что это то, что я пытаюсь сделать, хотя он не компилируется:Переопределение нескольких унаследованных шаблонных функций со специальными версиями

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

Итак, что я пытаюсь сделать, это своего рода класс-оболочку, чтобы наследовать из которого автоматически подключается производный класс к различным спискам обратных вызовов; он должен подключить конкретный экземпляр производного класса к списку, и я хочу, чтобы «пользователь» имел/получал возможность выполнять функции обратного вызова как часть создания производного класса, как вы можете видеть.

Кажется, что это должно работать, хотя мне может понадобиться использовать другой синтаксис. Если это не сработает, есть ли у вас какие-либо предложения?

ответ

-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 
+1

Это не компилируется (ССАГПЗ). Ваши объявления Derived :: my_callback не могут работать так. – Frunsi

+0

Это работает для меня; Обратите внимание: я использую Visual Studio 2008, который, как я знаю, имеет некоторые функции, которые не являются стандартными. Благодаря! – Narfanator

+0

Да, это побочный эффект поддержки явной реализации интерфейса. Вы будете в порядке, пока вы можете придерживаться 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 есть две версии my_callback() в классе Derived1, вы НЕ МОЖЕТЕ переопределить любой из t hem, вы можете только переопределить оба момента (например, Derived2 в примере)!

Вы должны просто предоставить два метода: «my_callback1()» и «my_callback2()».

-1

не виртуальность связанный с template вызывает тревогу в вашей голове? ;)

Вы должны выбрать свою сторону, статическую или динамическую.

+0

«Не так ли виртуальность, связанная с шаблоном, вызывает тревогу в вашей голове?» «Зачем? – curiousguy

0

Если использовать класс шаблона или не шаблонный, это можно сделать, используя вспомогательные классы в this style или this one.

(кажется, это единственное портативное решение, если вы не планируете использовать специальные квалифицированные имена Microsoft.)