说明用 C++ 编写抽象层的简单示例

Posted

技术标签:

【中文标题】说明用 C++ 编写抽象层的简单示例【英文标题】:Simple example to illustrate writing an abstraction layer in C++ 【发布时间】:2012-10-03 01:50:42 【问题描述】:

我只有 C++ 的基本知识。我正在尝试在 C++ 中实现硬件抽象层(HAL)。假设我想实现这个名为 Data 的类。基于平台,数据可以通过有线或无线方式发送。

class Data() 

public Data() 

//create random data



public sendData() 

// send data



public platform_action1() 

// do some platform specific action

// My HAL
    int HAL() 

    Data myData;

    myData.platform_action1();
    myData.sendData();

    return 0;
    

现在,如果我有有线和无线两个平台,我该如何扩展这个类并组织我的文件,以使HAL() 保持不变。

我也不想要动态绑定,即使用关键字“虚拟”。 在我的例子中,平台在编译时是已知的。

// 我不想这样做 :) ...

int HAL() 
Data* data = new WiredData();
data.sendData();

data = new WirelessData();

data.sendData();


在我的例子中,平台在编译时是已知的。

来自 C 世界,这就像填写平台特定的函数指针一样简单。

以 Boost C++ API 中的“线程”类为例。该类通过调用基于平台的 Windows 线程 API 或 Linux 线程 API 来自动生成线程。这样,我的 HAL 就真正独立于平台了。

谢谢 克里斯

【问题讨论】:

你应该尝试一些东西,如果它不起作用,问为什么。不要只要求人们填写空白。 【参考方案1】:

这更像是一个设计问题,而不是一个实际的 C++ 问题,但您要查找的术语是 polymorphism。您可以使用您的 Data 类并创建两个继承自它的类 WiredData 和 `WirelessData,这将使您能够执行以下操作:

Data data1 = new WiredData();
Data data2 = new WirelessData();

data1.sendData();
data2.sendData();

当您在 data1 和 data2 对象上调用 sendData() 时,多态性开始发挥作用,编译器将为每个特定子类型调用 sendData() 方法,即使它们被声明为 Data 类型

【讨论】:

猎人,我真的不想这样做:Data data1 = new WiredData();数据数据2 =新的无线数据();我只想在 sendData() 调用期间弄清楚数据连接。以 Boost C++ API 中的“线程”类为例。该类通过调用基于平台的 Windows 线程 API 或 Linux 线程 API 来自动生成线程。这样我的 HAL 就真正独立于平台了。【参考方案2】:

来自 C 世界,这就像填写平台特定的函数指针一样简单。

在 C++ 中几乎相同。您可以使 Data 类的 sendData() 函数 virtual(在签名前加上 virtual 关键字),然后派生指定适当的 sendData() 功能的有线和无线实现类。然后,您可以使用某种 if 语句来决定使用哪一个,并根据需要为 WiredWireless 对象保留一个 Data* 变量...当您调用 pointer->sendData() 时,它将调用相应的执行。这都是非常基础的——你应该在网上做一些介绍性的 C++ 教程,或者拿一本书。还有其他列出推荐培训材料的 *** 问题。

编辑:根据您在下面评论中的要求提供大纲。

class Wrapper

    Data* p_;
  public:
    void sendData()
    
        if (not p_)
            p_ = ... ? new Wired() : new Wireless();
        p_->sendData();
    

【讨论】:

托尼,感谢您的回复。想过做你提到的同样的事情。但是在 main() 调用中,我不想知道我下面是否有有线或无线平台。后期可以pointer->sendData()选择平台吗? virtual 函数的正确(大多数派生)版本在运行时解析,因此您无需知道main 中的实际类型是什么。这是一个核心语言特性;你应该按照 Tony 的建议找到一本书或教程。 请看Hunter回复的帖子。 @user1715819:当然——您可以将 Wires 与 Wireless 的决定移动到包装器类中,因此它会选择在方便的时候实例化哪一个。为此,您需要四个类:main() 直接使用的包装器、两个实现以及一个具有描述其共享 API 的虚函数的基类。 托尼...你能不能给我提供一下包装器的代码大纲。这个包装器是宏吗?知道 Boost C++ 中的“线程”类是如何实现的吗?【参考方案3】:

为什么不将更改的成员的定义放入名为的文件中:-

Data_Windows.cppData_Unix.cpp(例如)然后使用您的构建系统仅在该平台上的构建中包含相关文件?还是我在这里遗漏了什么……?

【讨论】:

【参考方案4】:
Can we do this using PIMPL(Private Implementation) approach? This is what I am thinking ...

// In Data.h

class PlatformDataProcess;                    // forward declaration of Pimpl
 
class Data

public:
   Data (const IPC& ipc); // process IPC
   ~Data();
 
   Data( const Data &rhs );   // undefined for simplicity
   Data& operator=( Data );
 
   void  process_ipc();
 
private:
   PlatformDataProcess *pimpl_;              // the Pimpl
;

// In Wired.cpp

#include "Data.h"
 
class PlatformDataProcess

public:
   void SendData()  // send data on wired
 
;


// In Data.cpp
 
Data::Data()  :  pimpl_( new PlatformDataProcess() )


 
Data::~Data()

   delete  pimpl_;

 
void   Data::SendData()

   pimpl_->SendData();      // do some private work   


int HAL() 

  // receive IPC

  Data* data = new Data(ipc);
  data->SendData();



So all the user needs to do is supply the platform specific file like wired.cpp .

【讨论】:

您对 pimpl_ (pimpl_( new PlatformDataProcess() )) 的初始化与有线与无线的选择有何关系?对于 OO 解决方案,需要在某个地方做出选择,new 用于有线或无线。当您添加该因素时,它就变成了一个状态模式。 pImpl 有相似之处,但其意图不是在运行时改变实现,而是隐藏实现(在 C++ 中,避免在客户端可见的类/头文件中添加/删除/更改私有成员时需要重新编译)。 托尼,实际上我选择了不好的例子,即有线和无线。在我的情况下,电路板有数据芯片 1 或芯片 2。 PlatformDataProcess 的编译时间定义很好,因为我不想在我的构建中包含所有芯片的代码。

以上是关于说明用 C++ 编写抽象层的简单示例的主要内容,如果未能解决你的问题,请参考以下文章

为 PHP 5.4 编写 C++ 扩展,示例代码已过时

Android HAL硬件抽象层的原理与应用实例

Android HAL硬件抽象层的原理与应用实例

Android HAL硬件抽象层的原理与应用实例

是否有 C++ DeckLink 输出的最小工作示例?

c++ 如何编写单进程named_mutex?