我可以在这个设计中使用dynamic_cast以外的东西吗?
Can I use something other than dynamic_cast in this design?
在我们的系统中,有
- 多个deviceTypes
- 每个deviceType可以有不同的配置类型
- 每个deviceType都是一个自己的库
我在一个情况下,我被迫使用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 objectn";
}
};
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()
确保配置对象在A0Device
=>中始终为A0Config
类型,在这里使用dynamic_cast是否安全?有没有更好的设计方法呢?
如果您可以支持额外的(在通用系统中最小,在实时/嵌入式系统中巨大)运行时开销,则可以安全地使用dynamic_cast<>
。
然而,你必须意识到这个"小"细节。给定表达式dynamic_cast<T*>(expr)
,当*expr
的动态类型既不是 T
,也不是T
的子类时,表达式求值为空指针nullptr
。当然,解引用nullptr
会调用未定义的行为,并且会在大多数平台上导致崩溃。
然而,检查nullptr
可能是不值得的,如果,只有当你知道你的代码会在这种情况下崩溃。
因为c++是一个碗,里面有汤和冰淇淋,土豆和咖啡,当然,每个想法都来自Stroustrup/c++委员会的耳朵/头脑,有几个替代方案:
- A 向下转换
static_cast<T*>(expr)
,尽管这与将某些内容转换为其他内容具有相同的问题。 - 对于那些觉得"必要"的C语言的人来说,
reinterpret_cast<T*>(expr)
在这里是不必要的,但它在那里。 - 如果你和都认为某件事在工程上是完美的,并且你知道所有对象在运行时可能在一个地方拥有的类型,你可以使用
enum for the type
与union for holding the data
、placement new
和explicit destructor calls
supercombo。 - 如果数据的东西涉及的问题,你可以有像
virtual Config &getConfig() = 0
的基础,和ABC123Config config; Config &getConfig { return this->config; }
的东西在派生。 - 对于像我这样的疯子, :使用c风格/构造器风格的强制转换。
希望这对你有帮助!
您可以在基类中拥有一个返回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 关系方面出现问题的线索。在这种情况下,A0Config
提供了一些不适合其基类Config
的功能(getA()
),可能它违反了sps - liskov替代原则,从而违反了强is - a 。
尽管如此,如果一个类关系可以用不止一种方式来表达,那么就使用最弱的关系——Herb Sutter
…肖恩·帕伦特就是这样。继承是evil的基类
- 如何理解C++标准N3337中的expr.const.cast子句8
- C++Cast运算符过载
- 在成员dynamic_bitset上使用 boost::from_block_range 时出错,但在本地dynamic
- C++类中的二维"dynamic"数组?
- 错误:"cast"未命名类型void setCastDescription(std::string
- 通过使用 const-cast 的非常量引用来延长临时的寿命
- "(void) cast"与功能有什么区别 "__attributes__"来沉默未使用的参数警告?
- protobuf in C++ with dynamic binding for google::protobuf::M
- 警告的原因是什么:"when type is in parentheses, array cannot have dynamic size"?
- C++:"Expected '(' for function-style cast or type construction"错误
- 为什么选择 g++ 给予者:"error: cast to pointer from integer of different size [-Werror=int-to-pointer-cast]"
- CUDA 错误:"dynamic initialization is not supported for __device__, __constant__ and __shared__ variabl
- Gtk+ g_signal_connect() 和 C++ lambda 会导致"invalid cast"错误
- 如何修复'The procedure entry point SDL_RWclose could not be located in the dynamic link library'
- Shared_ptr cast vs static_cast speed
- 在 iOS 上使用 Aruco 构建 OpenCV 时"Functional-style cast from id to double is not allowed"
- "The ordinal 344 could not be located in the dynamic link library"
- 覆盖 CAST 运算符(我认为它被称为向下转换)
- Dynamic Cast C++ Fail
- dynamic-cast-c++dynamic_cast错误处理