c++ - 关于 C++ 继承的初学者架构主题

标签 c++ inheritance architecture encapsulation

来自纯“C”,我是一个 C++ 新手,对 OO 开发或多或少是新手,因此我提前为我对以下主题的“幼稚”观点道歉。在下文中,我试图以抽象的方式描述我的问题(我的真实类是不同的)。代码部分可能无法编译,应仅被视为“想法”。

我有几个类,继承自一个基类:

    class Base
    {

    };


    class Derived1 : Base
    {

    };

    class Derived2 : Base
    {

    };

    class Derived3 : Base
    {

    };

此外, vector 包含指向派生类实例的指针:

    std::vector<Base *> collection;

现在我想提供这个类方案供其他用户使用。 问题:当用户遍历集合时,他/她如何知 Prop 体的类类型?为派生类提供虚拟成员函数不是一个好的选择,因为我事先不知道用户想要做什么。

他/她应该使用 dynamic_cast(...) 来获取具体类吗?不太好...

经过几个小时的思考,我最终得出了以下“解决方案”,但我不确定这是真的好还是完全是胡说八道:

为用户对象定义接口(interface),对上述类进行操作:

    class Derived1;
    class Derived2;
    class Derived3;

    class AbstractUserOperation
    {
        virtual void call(Derived1 * cl) = 0;
        virtual void call(Derived2 * cl) = 0;
        virtual void call(Derived3 * cl) = 0;
    };

用户基于该接口(interface)定义一个具体类,以实现他/她对我的派生类的每种可能类型的期望操作:

    class ConcreteUserOperation : AbstractUserOperation
    {
        virtual void call(Derived1 * cl)
        {
            ...
        }

        virtual void call(Derived2 * cl)
        {
            ...
        }

        virtual void call(Derived3 * cl)
        {
            ...
        }

    };

我自己的类(class)和以前一样,由“评估”扩展:

    class Base
    {
        virtual void evaluate(AbstractUserOperation* o) = 0;

    };


    class Derived1 : public Base
    {
        void evaluate(AbstractUserOperation *o)
        {
            o->call(this);
        }

    };

    class Derived2 : public Base
    {
        void evaluate(AbstractUserOperation *o)
        {
            o->call(this);
        }

    };

    class Derived3 : public Base
    {
        void evaluate(AbstractUserOperation *o)
        {
            o->call(this);
        }
    };

用法如下:

    std::vector<Base *> collection;

    ConcreteUserOperation o; // a user defined class, doing whatever with x

    x = collection[i];

    x->evaluate(&o); // call user defined operation o on x

当然,这有点“复杂”,但是,至少,一切都取决于用户定义具体的操作类,这与我的类方案完全分开。

从架构的角度来看,这种方法是否可以接受??? 希望这对这里的所有专家来说都不会太无聊 ;-)

非常感谢, 迈克尔

最佳答案

我不是这个访问者概念的专家,但我使用类似的代码并且我一直将其视为回调。我认为,如果您允许调用 Derived 的评估并使用 std::function 作为回调参数,您甚至不需要为 ConcreteUserOperation 定义接口(interface)。然后你甚至应该能够作为访问者插入 lambda。示例代码:

  #include <functional>

  struct Base {};

  struct Derived : public Base
  {
     void evaluate(std::function<void(const Derived&)> callback) const
     {
        callback(*this);
     }

     int foo = 42;
  };

  int main()
  {
     Derived d;
     d.evaluate([](const Derived& d){std::cout << d.foo << std::endl;});
  } 

生活例子: http://coliru.stacked-crooked.com/a/223af4a43077a760

关于c++ - 关于 C++ 继承的初学者架构主题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22311533/

相关文章:

jakarta-ee - 带有插件和嵌入式数据库的 Java EE 应用程序结构

c++ - 无法返回到用户输入行,也无法打印出电路板

c++ - 在 C++ 中排列文本输出

c++ - 部署的Qt应用程序QtWebEngineProcess无法加载Qt5Core.dll

java - 注解是否适用于子类?

c++ - 这种继承结构是否存在切片问题?

c++ - 复制构造函数不被继承

asp.net-mvc - 在 Multi-Tenancy 应用程序中使用多个数据库架构

ruby - 在 Ruby 中,是否有更好的方法根据传入的同名字符串选择常量(或完全避免常量)?

c++ - Lua 5.3 undefined reference