Я написал программу, которая использует виртуальные функции для достижения полиморфизма. У меня есть основной пользовательский класс, который слепо называет метод, который, по его мнению, является общими объектами (хотя они действительно должны быть специализированными). Эти объекты относятся к классам, которые переопределяют чистые виртуальные функции в своих базовых классах. Следующий адаптированный код должен продемонстрировать свою установку:Проблемы с реализацией полиморфизма
Общий класс (BaseConfig) в BaseConfig.h:
class BaseConfig {
public:
...
virtual void display() const = 0;
...
}
специализированная версия вышеуказанного общего класса (SpecialConfig) в SpecialConfig.h:
class SpecialConfig : public BaseConfig {
public:
...
void display() const;
...
}
реализация вышеуказанного специализированного класса в SpecialConfig.cpp:
...
void SpecialConfig::display() const {
// print some text
}
...
Теперь, когда я создаю указатель BaseConfig и устанавливаю его по адресу объекта SpecialConfig, вызов display() вызывает функцию display() класса SpecialConfig, как предполагается. Тем не менее, вещи расходятся с тем, что я ожидаю в следующих фрагментах кода до такой степени, что по какой-то причине после того, как объекты SpecialConfig возвращаются в очередь BaseConfig, вызов функции display() на них больше не ударяет по функции display() в SpecialConfig но вместо этого пытается использовать функцию display() в BaseConfig, вызывая выход из программы.
Вот общий класс для генерации перестановок конфигураций. Мы будем называть его BaseRuleSet в BaseRuleSet.h:
class BaseRuleSet {
public:
...
virtual queue<BaseConfig *> getValidChildConfigurations(BaseConfig * c) const = 0;
...
}
Его функция getValidChildConfigurations будет переопределен в специализированных классах Ruleset, как показано в классе SpecialRuleSet из SpecialRuleSet.h:
class SpecialRuleSet : public BaseRuleSet {
public:
...
queue<BaseConfig *> getValidChildConfigurations(BaseConfig * c) const;
}
Реализация выше класс в SpecialRuleSet.cpp:
...
queue<BaseConfig *> SpecialRuleSet::getValidChildConfigurations(BaseConfig * c) const {
queue<BaseConfig *> validChildConfigurations;
BaseConfig * baseConfigA;
BaseConfig * baseConfigB;
SpecialConfig specialConfigA;
SpecialConfig specialConfigB;
baseConfigA = &specialConfigA;
baseConfigB = &specialConfigB;
validChildConfigurations.push(baseConfigA);
validChildConfigurations.push(baseConfigB);
// validChildConfigurations.front()->display() works correctly here
return validChildConfigurations;
}
...
Как показано в комментарии выше, полиморфизм по-прежнему работает правильно в этой точке, так как специализированная функция отображения все еще попадает. Однако в этом последнем фрагменте кода (показано ниже) все разваливается. Это класс пользователя из User.cpp:
...
void User::doStuff() {
BaseRuleSet * baseRuleSet;
SpecialRuleSet specialRuleSet;
baseRuleSet = &specialRuleSet;
BaseConfig * currentConfig;
/*
SpecialConfig specialConfig;
currentConfig = &specialConfig;
currentConfig->display(); // this works
*/
queue<BaseConfig *> childConfigurations = ruleSet->getValidChildConfigurations(currentConfig);
childConfigurations.front()->display(); // this does not work
}
Как последний комментарий показывает, в приведенном выше примере, последний вызов, чтобы отобразить() на самом деле пытается использовать чистую виртуальную функцию в BaseConfig вместо реализованной специализированной версии в SpecialConfig.
Мои мысли - либо есть ограничение, либо другой способ делать вещи на C++, о которых я не знаю, или есть ошибки в моей реализации. Может ли кто-нибудь помочь прояснить это для меня?
Спасибо.
getValidChildConfigurations возвращает указатели на объекты, которые не существуют после завершения функции. – bmm6o