【问题标题】:How to prevent automatic downcasting when passing a superclass to/from a method将超类传递给/从方法传递时如何防止自动向下转换
【发布时间】:2013-08-05 12:10:28
【问题描述】:

我有几个从顶级超类派生的类:

基础:CDeviceClientRequest 子类:CDeviceSetEnabledRequest(基础) inst-class:CDeviceGPSSetEnabledRequest*(子类) inst-class: CDeviceTotalStationSetEnabledRequest*(子类)

只有标有 * 的才是可实例化的,其他的都有受保护的构造函数,即 构造函数调用基类构造函数,设置私有成员变量。

我正在通过一种方法构造它们:

CDeviceClientRequest getRequest(int type)
{
    switch (type)
    {
    GPS_SET_ENABLED: return CDeviceGPSSetEnabledRequest();
    TS_SET_ENABLED : return CDeviceTotalStationSetEnabledRequest();
    default:
       // raise an unknown type exception
    }
}

然后我有一些调用请求的代码:

void invoke(CDeviceClientRequest& request)
{
    // some code
}

所以我在某处有如下代码:

CDeviceClientRequest request = getRequest(GPS_SET_ENABLED);
invoke(request);

我的问题是,虽然我正在调用 CDeviceGPSSetEnabledRequest() 的构造函数, 从 getRequest() 返回的内容是 CDeviceClientRequest,以及传递给调用的内容 也是一个 CDeviceClientRequest,而不是我预期的 CDeviceGPSSetEnabledRequest。

我通过向 std::cout 的所有超类和基类添加一个简单的 whatAmI() 方法来验证这一点 类的名称,我只得到“我是 CDeviceClientRequest”。某处的事实 它正在处理派生类的信息已丢失。

非常感谢任何帮助。 (注:我已经大大简化了帖子的代码)。

【问题讨论】:

标签: c++


【解决方案1】:

问题是object slicing:当你按值返回时,你返回的是该类型的一个实例,即使它是从派生类型实例化的:

CDeviceClientRequest getRequest(int type);

这只能返回CDeviceClientRequest 类型的对象。你可以通过返回一个指向基类型的智能指针来解决这个问题。

std::unique_ptr<CDeviceClientRequest> getRequest(int type)
{
  switch (type)
  {
    GPS_SET_ENABLED: 
      return std::unique_ptr<CDeviceClientRequest>(new CDeviceGPSSetEnabledRequest);
    TS_SET_ENABLED : 
      return std::unique_ptr<CDeviceClientRequest>(new CDeviceTotalStationSetEnabledRequest);
    default:
   // raise an unknown type exception
  }

}

【讨论】:

  • 这是否也意味着我将调用更改为 void invoke(std::unique_ptr& request)。我需要做些什么特别的事情才能将原始实例化类从 unique_ptr 中取出吗?有问题的对象最终会出现在一个方法中,该方法将使用 boost 对其进行序列化。
  • @MarcusMacWilliam 你不需要,引用是多态的:对基类的引用可以引用派生对象。关于从智能指针“获取对象”,您可以将其视为通过-&gt; 获取其方法的指针,它还有一个取消引用运算符*,因此原则上您可以序列化的内容它管理的对象。
  • 如果我让getRequest() 返回一个std::unique_ptr,然后用invoke(*request) 传递对象来调用,我会不会有同样的问题。它不会自动将 CDeviceGPSSetEnabledRequest 向上转换为 CDeviceClientRequest 吗?
  • @MarcusMacWilliam 如果invoke 引用,则不会。
猜你喜欢
  • 2011-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-08-11
  • 2018-03-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多