Шаблоны C ++. Не могу использовать унаследованную функцию

Ну, это дало мне горе …

#include <iostream>

class InterfaceClass
{
public:
void test()
{
std::cout<<"Hello there.\n";
}
};

template <class T>
class TemplateClass
{
public:
T t;
};

class TestClass: public InterfaceClass
{};

class TestInheritor
{
public:
TemplateClass < InterfaceClass >* templateInherit;
InterfaceClass* normalInherit;

void test()
{
normalInherit->test();
templateInherit->t.test();
}

};

int main (int nargs, char ** arg)
{

TestInheritor ti;
ti.normalInherit = new TestClass; // THIS ONE COMPILES OKAY.

//ti.templateInherit = new TemplateClass <TestClass>; // COMPILE ERROR.

// THIS WORKS THOUGH
TemplateClass <TestClass> * tempClass = new TemplateClass <TestClass>;
ti.templateInherit=(TemplateClass <InterfaceClass>*)tempClass; // WHY DO I HAVE TO EXPLICITLY CAST?

// OUTPUT WORKS AS EXPECTED.
ti.test();

return 0;
}

Обычный пример наследования работает просто отлично. TestClass автоматически преобразуется в InterfaceClass. Однако, с примером шаблона, он дает ошибку компиляции:

error: cannot convert 'TemplateClass<TestClass>*' to 'TemplateClass<InterfaceClass>*' in assignment

На мой взгляд, очевидно, что вы можете преобразовать TemplateClass<TestClass>* в TemplateClass<InterfaceClass>*… Так чего мне здесь не хватает?

Я могу исправить это путем явного приведения класса шаблона к базовому классу, я могу без проблем использовать унаследованную функцию test () … Так почему я должен явно приводить класс шаблона?

Извините, если это сбивает с толку … Мне сложно объяснить эту проблему.


Хорошо, я понимаю проблему немного больше. Я решил добавить шаблон в TestInheritor следующим образом:

template <class T2>
class TestInheritor
{
public:
TemplateClass < T2 >* templateInherit;
InterfaceClass* normalInherit;

void test()
{
normalInherit->test();
templateInherit->t.test();
}
};

int main (int nargs, char ** arg)
{
TestInheritor <TestClass> ti;
ti.normalInherit = new TestClass;
ti.templateInherit = new TemplateClass <TestClass>;
ti.test();
return 0;
}

Возможно, не идеальное решение, но оно работает для моих целей.


Ах, и я вижу ваше решение:

#include <iostream>

class InterfaceClass
{
public:
void test()
{
std::cout<<"Hello there.\n";
}
};

class TestClass: public InterfaceClass
{};template <class T>
class TemplateClass
{
public:
T t;
};

template<>
class TemplateClass<TestClass> : public TemplateClass<InterfaceClass>
{
public:
};class TestInheritor
{
public:
TemplateClass < InterfaceClass >* templateInherit;
InterfaceClass* normalInherit;

void test()
{
normalInherit->test();
templateInherit->t.test();
}
};

int main (int nargs, char ** arg)
{
TestInheritor ti;
ti.normalInherit = new TestClass;
ti.templateInherit = new TemplateClass <TestClass>;
ti.test();
return 0;
}

0

Решение

Рассматривать

class Base
{};

class Derived : public Base
{};

template<typename T>
class TemplateClass
{};

Вопреки тому, что вы могли бы подумать, TemplateClass<Derived> это не TemplateClass<Base> в смысле наследования указатели на первое не могут быть неявно преобразованы в указатели на более поздние.

Итак, почему явно приведение указателя к TemplateClass<Derived> на указатель TemplateClass<Base> компилировать? Поскольку любой указатель определенного типа может быть явно приведен к любому указателю любого другого типа, однако нет никаких гарантий, что преобразование действительно! Вы могли бы, например, так же хорошо написать

int* i = (int*) new TemplateClass<Derived>;

и он скомпилируется просто отлично, хотя это явно недопустимое преобразование.

Теперь, почему ваш пример работает? Счастливой случайности. В тот момент, когда указатель, содержащий адрес, полученный посредством неверного приведения указателя, разыменовывается, программа становится недействительной и ее поведение не определено. Все может случиться, в том числе делать то, что вы ожидаете.

Если ты хочешь TemplateClass<Derived> быть TemplateClass<Base> в смысле наследования вы можете определить специализацию TemplateClass<> с явным указанием этой связи, например:

template<>
class TemplateClass<Derived> : public TemplateClass<Base>
{};
0

Другие решения

Других решений пока нет …

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector