Привет, у меня есть класс Tour
и GuidedTour
который расширяет Tour
. Я выполняю следующий код:
Tour* t;
if(x) {
t = new Tour(...);
}
else {
t = new GuidedTour(...);
}
Однако, когда я делаю следующее,
t->getDate();
(getDate()
относится к классу GuidedTour
)
Я получаю следующую ошибку
'class Tour' has no member named 'getDate'
Как я могу назвать этот метод?
У вас здесь две проблемы. Синтаксический, который другие ответы взяли на себя, чтобы обойти вас, и недостаток дизайна, к которому никто не обращался.
Синтаксическая проблема вызвана тем, что у Tour
нет метода getDate
. И все же вы пытаетесь вызвать эту функцию:
Tour* t;
// ... MAGIC HAPPENS
t->getDate(); // ERROR
Этот код сообщает компилятору "У меня есть указатель на объект Tour. Вызовите метод getDate() на нем". Но компилятор говорит: "Ум, Тур не имеет метода getDate()".
Вы знаете, что динамический тип объекта на самом деле является GuidedTour
, но компилятор этого не знает. Весь компилятор знает, что t
является указателем на Tour
.
Существует несколько способов решить эту разницу между тем, что знает компилятор, и тем, что вы знаете.
Один из них заключается в том, чтобы сделать getDate()
членом Tour
но если вы хотите, чтобы getDate()
был членом Tour
вы, вероятно, разработали его таким образом, в первую очередь.
Другой, чтобы сообщить компилятору, что вы знаете, что - то он не знает - что t
на самом деле указывает на GuidedTour
. Вы делаете это с помощью dynamic_cast
. Но если вы знаете что-то, что компилятор не знает, это обычно не потому, что компилятор глуп, а потому, что что-то не так с вашим дизайном - и это ваша вторая проблема. Вот почему я обычно говорю, что если у вас есть dynamic_cast
в вашей программе, вы должны более внимательно изучить ваш дизайн, потому что это часто свидетельствует о недостатке дизайна. Есть также потенциальные соображения производительности при использовании dynamic_cast
и, хотя они могут быть существенными, на мой взгляд, они все еще не являются основной проблемой для dynamic_cast
.
Можете добавить
virtual Date GetDate() { throw std::exception("unimplemented"); }
в класс Tour и сделать GetDate виртуальным в GuidedTour. Вы также можете использовать:
dynamic_cast<GuidedTour*>(t)->GetDate()
if (GuidedTour * guidedTour = dynamic_cast<GuidedTour*>(t)) { ... guidedTour->GetDate() ...}
.
if(x) { t->GetDate(); }
с тем же x, что и в вопросе.
Проблема заключается в том, что вы объявили т как Тур. Несмотря на то, что позже вы активируете его как GuidedTour, у Tour нет функции getDate(), поэтому ошибка. Вы можете назвать это, сначала набросив его как GuidedTour:
GuidedTour *tAsGuidedTour = dynamic_cast<GuidedTour*>(t)
if (tAsGuidedTour != NULL)
{
tAsGuidedTour->getDate();
}
EDIT: вы можете прочитать http://www.cplusplus.com/doc/tutorial/typecasting/ для лучшего понимания
Образец:
#include"stdio.h"
class Tour
{
public:
Tour(){}
~Tour(){}
int getDate()
{
printf("Func Display!\n");
return 0;
}
private:
///
};
class GuidedTour:public Tour
{
public:
GuidedTour(){}
~GuidedTour(){}
private:
///
};
int main()
{
int x;
Tour *t;
scanf("%d",&x);
if(x) t=new Tour;
else t=new GuidedTour;
t->getDate();
return 0;
}
возможно, вы расширили частную часть класса "Тур".
getDate()
является специфическим для GuidedTour
, он не GuidedTour
в базовый класс Tour
.
static_cast
(который успешно выполняется внутри иерархии классов).dynamic_cast
говорит, что в коде есть специальная обработка для определенных подклассов. Конечно, гораздо приятнее поместить абстракцию в базовый класс с использованием виртуальных или абстрактных методов и иметь специализированное поведение в производных классах, потому что в этом и заключается смысл создания классов.