【问题标题】:Simple example to illustrate writing an abstraction layer in C++说明用 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 就真正独立于平台了。

  • 谢谢 克里斯

【问题讨论】:

  • 你应该尝试一些东西,如果它不起作用,问为什么。不要只要求人们填写空白。

标签: c++


【解决方案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++ 教程,或者拿一本书。还有其他列出推荐培训材料的 stackoverflow 问题。

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

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 的编译时间定义很好,因为我不想在我的构建中包含所有芯片的代码。
    猜你喜欢
    • 2017-03-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-08-24
    • 2013-03-21
    • 2011-02-25
    相关资源
    最近更新 更多