[英]Can I use something other than dynamic_cast in this design?
在我们的系统中,
我处于不得不使用dynamic_cast的情况。 我想知道是否有更好的方法来设计它?
我所拥有的是:
// in common code
class Config {public: virtual ~Config(){} };
class Device {
protected:
Config* devConfig;
protected:
virtual void createDevConfig() = 0;
public:
virtual void display() = 0;
};
// Device specific Code
class A0Device : public Device {
protected:
virtual void createDevConfig() { this->devConfig = new A0Config(); }
public:
A0Device() { this->createDevConfig(); }
virtual void display(){
A0Config* config = dynamic_cast<A0Config*>(this->devConfig);
if(!config) std::cout << "Null object\n";
}
};
class A0Config : public Config {};
int main() {
Device* dev = new A0Device();
dev->display();
return 0;
}
本质上, A0Device
具有自己的配置类型: A0Config
,由其他成员组成。 A0Device在基类devConfig
定义为Config*
。 在A0Device::display()
-我需要访问devConfig对象(作为A0Config
类型)。 virtual createDevConfig()
确保config对象在A0Device
始终为A0Config
类型=>在此处使用dynamic_cast是否安全? 有没有更好的设计方法?
如果您可以支持额外的(在通用系统中为最小,在实时/嵌入式系统中为最小)运行时开销,则可以安全地使用dynamic_cast<>
。
但是,您必须意识到这个“小”细节。 给出的表达式dynamic_cast<T*>(expr)
,每当动态类型的*expr
既不 T
或子类T
, 表达evalutates为空指针, nullptr
。 而且,当然, 取消引用nullptr
调用未定义的行为,并且将在大多数平台上导致崩溃 。
但是, 仅当您知道您的代码在这种情况下会崩溃时,检查nullptr
可能不值得。
因为C ++是一碗盛有汤和冰淇淋,土豆和咖啡的碗,而且当然,每个想法都来自Stroustrup / C ++受托人的耳朵/头脑,所以有几种选择:
static_cast<T*>(expr)
,尽管这与将某些内容转换为不是的东西具有相同的问题。 reinterpret_cast<T*>(expr)
,但它在那里。 union for holding the data
enum for the type
使用enum for the type
union for holding the data
带有placement new
union for holding the data
。 explicit destructor calls
supercombo。 virtual Config &getConfig() = 0
之类的东西,以及诸如ABC123Config config; Config &getConfig { return this->config; }
类的东西ABC123Config config; Config &getConfig { return this->config; }
ABC123Config config; Config &getConfig { return this->config; }
ABC123Config config; Config &getConfig { return this->config; }
。 希望这可以帮助!
您可以在基础中有一个纯虚函数,该虚函数返回Config
指针或引用(除非需要指针,否则我希望使用该指针),然后将其存储在派生类中。 这个问题/答案涵盖了指针和引用之间的区别: 何时使用引用与指针
这种设计的优势在于,基础中任何需要Config
东西都可以使用getConfig
,而任何需要使用派生类的东西都可以不进行强制转换。 另外,您无需调用new
和delete
。
class Device {
protected:
virtual Config& getConfig() = 0;
...
};
class A0Device {
public:
...
Config& getConfig() {return config;}
...
private:
A0Config config;
};
[不确定,如果我在这里缺少什么,但是听起来或多或少听起来像是设计的气味]
为什么A0Config
无法聚合Config
?
通常,点击dynamic_cast
可以暗示在建立IS-A关系方面有些dynamic_cast
。 在这种情况下, A0Config
提供了一些不适合其基类Config
功能( getA()
),也许它违反了LSP-Liskov替换原理,从而违反了强的IS-A 。
但是, 如果可以用一种以上的方式表达阶级关系,请使用最实用的最弱关系– Herb Sutter
...而肖恩·帕特恩(Sean Parent)达到了这种程度。 继承是邪恶的基础
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.