【问题标题】:Avoiding Downcasting避免垂头丧气
【发布时间】:2018-10-31 17:20:04
【问题描述】:

在使用接口时如何防止向下转换?我已经阅读了一些关于 stackoverflow 的答案,如果你不得不向下转型,那么你很可能有一个弱接口。那你们是怎么做的,正确的方法是什么?我有一个具体的例子,我想知道如何正确避免向下转换。在我的示例中,我有一个用于传递数据的接口,但具体实现可能包含唯一属性。在 A 类和 B 类中,我需要向下转换为 DataType1 或 DataType2,因为它们具有可以返回的不同属性类型。

struct IData
{
    virtual ~IData();
};

struct IAction
{
    virtual ~IAction();
    virtual void setup(IData& data) = 0;
};

class DataType1 : public IData
{
    int data1;
public:
    DataType1();
    int getData1();
};

class DataType2 : public IData
{
    std::string data2;
public:
    DataType2();
    std::string getData2();
};

class A : public IAction
{
public:
    A();
    void setup(IData& data) override;
}

class B : public IAction
{
public:
    B();
    void setup(IData& data) override;
}

【问题讨论】:

  • IData 应该提供所需的方法(可以返回数据,也可以返回另一个返回数据的接口)
  • 这对于softwareengineering.stackexchange.com(设计模式)来说是一个合适的问题
  • 我会问一个问题为什么你希望这些有一个共同的界面?它们显然是不同的类型,为什么不只是具有采用不同类型数据参数的重载函数呢?
  • 初始化不可能永远是100%通用的,因为至少你需要实例化一个特定的类型。因此,当您创建对象时,您必须知道它的完整类型。那是你通常初始化它的时候。每种不同的类型都可以根据自己的特定怪癖进行初始化。只有在此之后,您才能将其传递给系统中不需要知道其确切类型的部分。
  • 如果您真的想要一个通用初始化,那么如果您从一个通用类型(如文件或文本字符串)进行初始化,那么它可以通过一个通用接口来完成。每种类型都接收相同的输入,但根据自己的需要对其进行解析。这意味着IData 将是一个 fixed 类型。然后你可以避免向下转换。

标签: c++ c++11 c++14


【解决方案1】:

在我看来,在代码中包含向下转换指令并不是什么大问题。据我所知,这件事是有效的,这就是为什么 C++ 有 dynamic_cast 操作。

【讨论】:

    【解决方案2】:

    你的接口应该定义你需要在子类上调用的所有方法作为虚拟方法(如果是纯虚拟方法更好)。

    在这种情况下,您的接口可以有 2 个虚拟方法 getData 或者如果您使用 c++17 或更高版本编译,您可以尝试使用 std::any

    【讨论】:

      猜你喜欢
      • 2021-12-25
      • 2010-12-04
      • 2019-02-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-07-31
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多