【问题标题】:How to use derived parameter in an overriding function without dynamic casting如何在没有动态转换的覆盖函数中使用派生参数
【发布时间】:2019-07-01 21:17:11
【问题描述】:

谁能告诉我如何实现:

  • 派生类方法的参数是参数的 派生类(不是参数的基类)?

这就是我想要的:

class Base{
public:
    // Base class method has ParameterBase parameter
    virtual void f(ParameterBase pb) = 0;
}

class Derived : public Base{
public:
    // I want: Derived class method has ParameterDerived parameter;
    void f(ParameterDerived pd){ //do something with pd; }
}

class ParameterBase{
    // Base class of parameter;
}

class ParameterDerived : public ParameterBase{
    // Derived class of parameter;
}

以上如何实现? 我必须在派生方法的参数列表中使用 ParamterBase 并在方法体中动态转换参数吗?

【问题讨论】:

    标签: c++ parameters polymorphism overriding


    【解决方案1】:

    您要求的功能称为参数类型逆变。不幸的是,C++ 不支持它。 C++ 仅支持返回类型协方差。 See 这里有一个很好的解释。

    也许不方便的是,C++ 不允许我们编写函数 标记嗯...上面。 C++ 的经典 OOP 系统支持“协变 返回类型”,但它不支持“逆变参数 类型。”

    但您可以使用dynamic_cast<>() 运算符。但首先,您必须将参数类型更改为指针或引用,并在class ParameterBase 中添加至少一个虚拟成员(虚拟析构函数也算在内),以使编译器为其创建虚拟方法表。这是带有参考的代码。可以改用指针。

    class ParameterBase
    {
        public:
            // To make compiler to create virtual method table.
            virtual ~ParameterBase()
            {}
    };
    
    class ParameterDerived : public ParameterBase
    {
    };
    
    
    class Base
    {
        public:
            // Pointers or references should be used here.
            virtual void f(const ParameterBase& pb) = 0;
    };
    
    class Derived : public Base
    {
        public:
            virtual void f(const ParameterBase& pb) override
            {
                // And here is the casting.
                const ParameterDerived& pd=dynamic_cast<const ParameterDerived&>(pb);
    
            }
    };
    
    
    int main()
    {
        Derived d;
        ParameterDerived p;
    
        d.f(p);
    }
    

    【讨论】:

      【解决方案2】:

      假设您希望使用 ParameterDerived 调用 Derived,但您还希望在抽象基类中声明接口。

      接口必须具有相同的参数类型,但您仍然可以在 Derived::f 中使用 dynamic_cast 强制执行正确的参数子类

      #include <iostream>
      #include <string>
      
      // interface
      struct ParameterBase {
          virtual ~ParameterBase() {};
      };
      
      struct Base {
          virtual void f(ParameterBase *pb) = 0;
          virtual ~Base() {};
      };
      
      // specific
      struct ParameterDerived : public ParameterBase {
          std::string name;
          ParameterDerived(const std::string &name) : name(name) {}
          ParameterDerived& operator=(const ParameterDerived& rhs) { name = rhs.name; }
          ~ParameterDerived() {};
      };
      
      struct Derived : public Base {
          Derived(){}
          Derived& operator=(const Derived &rhs) {}
          virtual ~Derived(){}
      
          void f(ParameterBase *pb) {
              ParameterDerived *pd = dynamic_cast<ParameterDerived*>(pb);
              if (pd) {
                  std::cout << "Derived object with derived parameter " << pd->name << std::endl;
              } // else {throw std::exception("wrong parameter type");}
          }
      };
      
      int main() {
          Derived object;
          ParameterDerived param("foo");
          object.f(&param);
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2023-03-09
        • 1970-01-01
        • 2018-12-23
        • 2013-09-11
        • 1970-01-01
        • 2020-01-16
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多