Russian Qt Forum

Программирование => С/C++ => Тема начата: System от Март 30, 2015, 10:19



Название: Шаблоны, наследование и методы
Отправлено: System от Март 30, 2015, 10:19
Имеется следующий код:
Код
C++ (Qt)
#include <cstdio>
 
template<int N> class Tmpl {
   private :
       void _f() {
           printf("Template. %d\n", N);
       }
   public :
       void f() {
           _f();
           printf("%d\n", N);
       }
};
 
class Instance : public Tmpl<1> {
   private :
       void _f() {
           printf("Instance.\n");
       }
};
 
int main() {
   Instance* instance = new Instance();
   instance->f();
   delete instance;
   return 0;
}
 
Результат выполнения:
Код
DOS
Template. 1
1
Необходимо изменить этот код так, чтобы вместо Tmpl::_f вызывалась Instance::_f.

Первое решение - объявить _f виртуальной. Однако, это решение использовать в данном случае нельзя. Как ещё можно добиться требуемого результата?


Название: Re: Шаблоны, наследование и методы
Отправлено: System от Март 30, 2015, 11:33
Нашёл один вариант:
Код
C++ (Qt)
#include <cstdio>
#include <cassert>
 
template<int N, class Derived> class Tmpl {
   private :
       void _f() {
           printf("Template. %d\n", N);
       }
   public :
       void f() {
           static_cast<Derived*>(this)->_f();
           printf("%d\n", N);
       }
};
 
class Instance : public Tmpl<1, Instance> {
   friend class Tmpl<1, Instance>;
   public :
       void _f() {
           printf("Instance.\n");
       }
};
 
int main() {
   Instance* instance = new Instance();
   instance->f();
   delete instance;
 
return 0;
}
 
Может, есть другие решения? Какое-то оно... Через одно место, как мне кажется...


Название: Re: Шаблоны, наследование и методы
Отправлено: _Bers от Март 30, 2015, 14:42
http://rextester.com/QGDYN30725

Код:
#include <cstdio>
 
template<class T, int N> struct Tmpl
{
    void f()
    {
        static_cast<T*>(this)->_f();
        printf("%d\n", N); 
    }
};
 
struct Instance : Tmpl<Instance, 1>
{
    void _f() { printf("Instance.\n"); }
};
 
int main() {
    Instance* instance = new Instance();
    instance->f();
    delete instance;
    return 0;
}


Название: Re: Шаблоны, наследование и методы
Отправлено: Igors от Март 31, 2015, 09:01
С интересом наблюдал за темой, тоже нашел это решение, но подумал что private обходить нельзя, поэтому не годится. Скажите, а есть еще какие-то пути или только этот единственный?

Спасибо


Название: Re: Шаблоны, наследование и методы
Отправлено: System от Март 31, 2015, 09:51
К сожалению, private обходить действительно нельзя. Функция _f() должна быть скрытой от кода, использующего класс. Максимум - объявить protected.  ;) Решение со static_cast и friend мне не очень нравится, но, похоже, придётся реализовывать именно его в связи с отсутствием других предложений.


Название: Re: Шаблоны, наследование и методы
Отправлено: System от Март 31, 2015, 10:12
Можно чуть упростить код, написав
Код
C++ (Qt)
friend class Tmpl;
вместо
Код
C++ (Qt)
friend class Tmpl<1, Instance>;