наследование — использование c ++ ковариации для получения подтипа объекта

Следующий код генерирует объект подтипа, как и ожидалось, но его приведение по умолчанию является супер указателем на подобъект. Может кто-нибудь сказать мне, почему это?

class super {
virtual super* get_clone() = 0;
}
class subA : super {
sub* get_clone() { return new subA(); };
}
class subB : super {
sub* get_clone() { return new subB(); };
}

subA a;
super *s = &a;

Теперь, если я запускаю s-> get_clone () в GDB, я получаю:

(gdb) p s->get_clone()
(super *)0x7fff7c

Я не понимаю, почему он возвращает (супер *) указатель вместо (subA *) указателя. Я понял, что могу просто привести указатель, но я пытался создать шаблонный код на основе возвращенного подтипа.

Спасибо!

0

Решение

Компилятор не может знать, какой фактический конкретный класс объекта будет указывать во время выполнения. Он только знает, что указатель будет указывать на экземпляр подкласса s.

class super
{
public:
virtual super* get_clone() = 0;
};

class subA : public super
{
public:
subA* get_clone()
{
std::cout << "subA::get_clone()\n";
return new subA();
};
};

class subB : public super
{
public:
subB* get_clone()
{
std::cout << "subB::get_clone()\n";
return new subB();
};
};

int main()
{
subA a;
super *s1 = &a;
super* s2 = s1->get_clone();
//subA* s3 = s1->get_clone();  // compile error here; the compiler doesn't know what is the concrete class s points to.

subA* a1 = &a;
subA* a2 = a1->get_clone();  // here it can know that the returned pointer is to subA.

}
0

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

Какие gdb сообщил правильно. Он сообщает тип возврата для вызванного вами метода. Хотя реализация виртуального метода имеет другой тип возвращаемого значения, возвращаемое значение «преобразуется» в тип возвращаемого значения, возвращаемый вызванным вами методом.

Как было отмечено в комментариях, динамическая привязка виртуального метода get_clone() не поддается сценарию статического связывания. Любое статическое связывание, которое вы можете захотеть сделать, может быть выполнено внутри подтипов, связанных через супер. Одним из методов, который вы могли бы использовать для достижения этой цели, была бы функция шаблона стиля CRTP, предоставляемая супер:

class super {
virtual super * get_clone () = 0;
protected:
template <typename SUB> SUB * get_clone_common (SUB *) {
//...
return new SUB;
}
};

class subA : super {
subA * get_clone () { return get_clone_common(this); }
};

В приведенном выше примере subA выполняет статическое связывание через интерфейс шаблона, предоставленный super,

0

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