在我们的系统中,我们有
我遇到了被迫使用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()
确保配置对象在A0Config
=&gt;中始终为A0Device
类型在这里使用dynamic_cast是否安全?有没有更好的设计方法?
答案 0 :(得分:2)
如果您可以支持额外的(通用系统中最少的,实时/嵌入式系统中很少)运行时开销,则可以安全地使用dynamic_cast<>
。
但是,您必须了解这个“小”细节。给定dynamic_cast<T*>(expr)
表达式,只要*expr
的动态类型既不是 T
,也不是T
的子类,,表达式会重新评估为空指针nullptr
。当然,解除引用nullptr
会调用未定义的行为,并会导致大多数平台崩溃。
但是,检查nullptr
可能不值得,只有当您知道您的代码会在这种情况下崩溃时。
因为C ++是一个包含汤和冰淇淋,土豆和咖啡的碗,当然,每个想法都来自Stroustrup / C ++委员会的耳朵/思想,有几种选择:
static_cast<T*>(expr)
,虽然这与将某些东西投射到其他东西上的问题相同但不是。reinterpret_cast<T*>(expr)
在此不是必需的,但它就在那里。enum for the type
union for holding the data
与placement new
explicit destructor calls
和virtual Config &getConfig() = 0
supercombo。ABC123Config config; Config &getConfig { return this->config; }
,并在Derived中使用foldr (\c (x:xs) ->
if c == '/'
then "":x:xs
else (c:x):xs
) [""] "hello/my/friends"
。希望这有帮助!
答案 1 :(得分:1)
你可以在基础中有一个纯虚函数,它返回一个Config
指针或引用(除非你需要一个指针,我更喜欢它),然后在派生类中存储。这个问题/答案涵盖了指针和参考文献之间的差异:When to use references vs. pointers
这种设计的优点是基础中需要Config
的任何东西都可以使用getConfig
,而任何需要使用派生类的东西都可以不进行强制转换。此外,您无需致电new
和delete
。
class Device {
protected:
virtual Config& getConfig() = 0;
...
};
class A0Device {
public:
...
Config& getConfig() {return config;}
...
private:
A0Config config;
};
答案 2 :(得分:0)
[不确定,如果我在这里遗漏了一些东西,但它或多或少听起来像是一种设计气味]
为什么A0Config
无法汇总Config
?
通常,点击dynamic_cast
是一个线索,表明在建立 IS-A 关系方面有些不对劲。在这种情况下,A0Config
提供了一些不适合其基类getA()
的功能(Config
),可能违反了LSP-Liskov Substitution Principle,从而违反了强大的IS- A 强>
...而Sean Parent就是这样。 Inheritance is the base class of evil