不同版本的设备的代码结构
Code structure for different versions of devices
我正在编写"设备驱动程序"(C 14(,该版本可以处理用于不同版本的设备的多个版本。该设备驱动程序正在使用基于HTTP的协议通过以太网通过以太网通信的外部PC上运行。所有版本都有共同的功能,但是在协议的某些版本中,某些功能可能会增加。
以下是一个示例:
class ProtocolBase {
public:
virtual void reset_parameters() {
std::cout << "reset parameters" << std::endl;
}
virtual void set_parameters() {
std::cout << "set parameters" << std::endl;
}
};
class ProtocolV1 : public ProtocolBase
{
public:
void set_parameters() override {
std::cout << "set parameters for V1" << std::endl;
}
};
class ProtocolV2 : public ProtocolBase
{
public:
void set_parameters() override {
std::cout << "set parameters for V2" << std::endl;
}
void reset_parameters() {
std::cout << "reset parameters for V2" << std::endl;
}
void do_V2() {
std::cout << "doing V2" << std::endl;
}
};
以下是main
:
int main(int argc, char const *argv[])
{
int version = std::atoi(argv[1]);
std::unique_ptr<ProtocolBase> protocol = std::make_unique<ProtocolV1>();
switch (version)
{
case 1:
/* do nothing at the moment */
break;
case 2:
protocol.reset(new ProtocolV2);
break;
default:
break;
}
protocol->reset_parameters();
if(ProtocolV2* p = dynamic_cast<ProtocolV2*>(protocol.get())) { //not sure about this
p->do_V2();
}else {
std::cout << "This functionality is unavailable for this device" << std::endl;
}
protocol->set_parameters();
return 0;
}
我有一种使用dynamic_cast
的感觉,不是最好的方法。期待一些反馈。
编辑:根据 @ptaq666的答案,我修改了 ProtocolBase
和 ProtocolV2
as:
class ProtocolBase {
public:
virtual void do_V(){
std::cerr << "This functionality is unavailable for this device" << std::endl;
}
};
class ProtocolV2 : public ProtocolBase
{
public:
void do_V() override {
std::cout << "doing V2" << std::endl;
}
};
这样,不再需要dynamic_cast
,尽管基类必须知道所有功能。这似乎是目前最好的解决方案。
在大多数情况下选择适当的系统体系结构时,答案是"这取决于" :(。最舒适的解决方案是引入特定于协议的行为其构造函数中的ProtocolBase
子类
class ProtocolV2 : public ProtocolBase
{
public:
ProtocolV2::ProtocolV2(args) {
// set some params that will determine when do_V2() is called
// it can be some numeric setting, a callback, or similar
}
void set_parameters() override {
// you can use V2 behavior here maybe?
std::cout << "set parameters for V2" << std::endl;
}
void reset_parameters() override {
// or here maybe?
std::cout << "reset parameters for V2" << std::endl;
}
private:
void do_V2() {
std::cout << "doing V2" << std::endl;
}
};
如果由于某种原因无法执行此操作,则有可能将do_V2()
作为公共非虚拟方法,但要在将ProtocolV2
作为ProtocolBase
的指针传递之前调用它到将使用它的Sysytem。当然,限制是do_V2
只能在外面调用您的系统范围,这可能无法真正解决问题。
另一个选择是实际将do_V2()
移至接口:
class ProtocolBase {
public:
virtual void reset_parameters() {
std::cout << "reset parameters" << std::endl;
}
virtual void set_parameters() {
std::cout << "set parameters" << std::endl;
}
virtual void do_V2() {
std::cout << "not supported" << std::endl;
}
};
默认情况下将其作为"不支持"行为实现。只有ProtocolV2
才能实现此行为作为协议的有效部分。
最后,如果以上都没有,那么您当然可以按照您的建议使用Dynamic_cast。我个人尝试避免dynamic_cast
,因为我的办公室伴侣肯定会开始滥用它,但是在某些情况下,这是一个正确的解决方案。
另外,如果您决定施放指针,请使用std::shared_ptr
使用dynamic_pointer_cast
,而不是从unique_ptr
访问RAW指针。
通常,这取决于派生类ProtocolV1
和ProtocolV2
的形成方式,如果各自的成员功能将使用不同的数据成员,则数据成员和天气是什么!p>原因仅仅是因为成员数据没有依赖性,因此成员函数仅对他们已调用的对象的 type !
就像具有(非成员(函数超载一样:
void function(ProtocolV1 *){
std::cout << "set parameters for V1" << std::endl;
}
void function(ProtocolV2 *){
std::cout << "set parameters for V2" << std::endl;
}
,然后通过类型ProtocolV1 *
的指针调用一次,并使用 ProtocolV2 *
类型的空指针。
如果您喜欢在问题中介绍的用法的替代方案,甚至可以使用C风格的演员:结果是相同!
最后,如果您要调用成员函数以调用它的另一个函数,该函数需要某些数据成员/s,则是/s 不同的,跨派生的类别作为参数/s,那么,除非您引入某种形式的补偿来填写铸件类型中未提供的数据!
祝你好运!
- 孤立代码块在结构中引发异常
- 如何使用boost::具有嵌套结构和最小代码更改的序列化
- 为什么Microsoft在新代码中使用结构而不是类?
- 如何使用结构体在C++中更改这些代码?
- 在 Golang 中等C++结构中提供代码提示/标记
- clang:错误:链接器命令失败,退出代码为 1(使用 -v 查看调用) - 体系结构的未定义符号 x86_64:
- 如何知道用于实现标准代码段的确切数据结构和算法,例如在C++STL中?
- 我觉得我放入结构中的输入代码可以压缩,关于如何在保持代码简短的同时保持数据个性化的任何建议?
- 如何大致将 cpp 代码结构转换为 python
- 设计许多单例代码结构的更好方法
- 在正确性或良好的代码结构方面,这种动态对象创建看起来如何
- 不同版本的设备的代码结构
- 非常简单的C 文本冒险的代码结构
- Windows MSG 结构与旧项目代码结构 MSG 冲突
- 我可以让 c++ 代码结构相互看到吗?
- 存储类指针矢量(RPG代码结构)
- Rcpp:将数据帧与 Rcpp(内联)一起使用时推荐的代码结构
- 破译c++代码:结构中的函数与结构同名
- c++代码结构转换成HTML文件
- 有没有可以可视化c++代码结构的程序?