【发布时间】:2012-01-16 19:19:59
【问题描述】:
我写了一个程序,它使用虚函数来实现多态性。我有一个主 User 类,它盲目地调用它认为是通用对象的方法(尽管它们实际上应该是专门的)。这些对象来自在其基类中覆盖纯虚函数的类。以下修改后的代码应演示我的设置:
BaseConfig.h 中的一个泛型类(BaseConfig):
class BaseConfig {
public:
...
virtual void display() const = 0;
...
}
SpecialConfig.h 中上述泛型类(SpecialConfig)的专门化版本:
class SpecialConfig : public BaseConfig {
public:
...
void display() const;
...
}
上述特殊类在SpecialConfig.cpp中的实现:
...
void SpecialConfig::display() const {
// print some text
}
...
现在,当我创建 BaseConfig 指针并将其设置为 SpecialConfig 对象的地址时,调用 display() 会按预期命中 SpecialConfig 类的 display() 函数。但是,事情与我在以下代码 sn-ps 中所期望的不同,由于某种原因,在 BaseConfig 队列中返回 SpecialConfig 对象后,在它们上调用 display() 函数不再命中 display() 函数在 SpecialConfig 中,而是尝试在 BaseConfig 中使用 display() 函数,导致程序退出。
这是一个用于生成配置排列的通用类。我们将在 BaseRuleSet.h 中称其为 BaseRuleSet:
class BaseRuleSet {
public:
...
virtual queue<BaseConfig *> getValidChildConfigurations(BaseConfig * c) const = 0;
...
}
它的 getValidChildConfigurations 函数将在专用 RuleSet 类中被覆盖,如 SpecialRuleSet.h 中的 SpecialRuleSet 类所示:
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;
}
...
如上面的评论所示,此时多态性仍然正常工作,因为专门的显示功能仍在被击中。但是,在最后一个代码 sn-p(如下所示)中,一切都崩溃了。这是来自 User.cpp 的 User 类:
...
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
}
正如上例中最后一条注释所示,最后一次调用 display() 实际上尝试使用 BaseConfig 中的纯虚函数,而不是 SpecialConfig 中实现的专用版本。
我的想法是在 C++ 中存在我不知道的限制或不同的做事方式,或者我的实现中存在错误。谁能帮我澄清一下?
谢谢。
【问题讨论】:
-
getValidChildConfigurations 返回指向函数完成后不存在的对象的指针。
标签: c++ polymorphism