【问题标题】:assigning derived class pointer to base class pointer in C++在 C++ 中将派生类指针分配给基类指针
【发布时间】:2012-11-19 09:08:40
【问题描述】:

我有关注

class base
{
};

class derived : public base
{
  public:
   derived() {}
   void myFunc() { cout << "My derived function" << std::endl; }

};

现在我有

base* pbase = new derived();
  pbase->myFunc();

我收到错误 myFunc is not a member function of base.

如何避免这种情况?以及如何让 myFunc 被调用?

注意我应该让基类不包含任何功能,因为它是设计的一部分,上面的代码是大功能的一部分

【问题讨论】:

    标签: c++


    【解决方案1】:

    如果您坚持认为此功能不应成为基础的一部分,那么您只有 2 个选择。

    要么使用指向派生类的指针

    derived* pDerived = new derived();
    pDerived->myFunc();
    

    或者(uglier & 强烈不鼓励)将指针静态转换为派生类类型,然后调用函数
    注意谨慎使用。仅当您确定要转换的指针的类型时才使用,即您确定 pbasederived 或派生自 derived 的类型。在这种特殊情况下它没问题,但我猜这只是实际代码的一个例子。

    base* pbase = new derived();
    static_cast<derived*>(pbase)->myFunc();
    

    【讨论】:

    • static_cast 在这里非常不安全。很容易导致各种麻烦。
    • static_castdynamic_cast 会返回的某些情况下不会返回空指针。例如,它允许从derived2 对象转换为derived 对象,即使它们不在同一个继承分支中。
    • 将派生类指针分配给基类有什么好处?我猜 virtual 是不同的情况,如果功能不是虚拟的,有什么用法吗?如果有覆盖,使用基类指针访问函数将仅访问基类函数。所以我不确定它的用法。
    【解决方案2】:

    myfunc 需要可从基类访问,因此您必须在 base 中声明公共虚拟 myfunc。如果您打算将 base 用作抽象基类,即无法实例化并充当接口的类,则可以将其设为纯虚拟:

    class base
    {
     public:
      virtual void myfunc() = 0; // pure virtual method
    };
    

    如果您希望能够实例化base 对象,那么您必须为myfunc 提供一个实现:

    class base
    {
     public:
      virtual void myfunc() {}; // virtual method with empty implementation 
    };
    

    如果您想从指向基类的指针访问函数,没有其他干净的方法可以做到这一点。最安全的选择是使用dynamic_cast

    base* pbase = new derived;
    
    ....
    derived* pderived = dynamic_cast<derived*>(pbase);
    if (derived) {
      // do something
    } else {
      // error
    }
    

    【讨论】:

    • 不应该myfunc() 成为公众成员吗?
    【解决方案3】:

    要使用基类指针,您必须将基类定义更改为:

    class base
    {
    public:
        virtual void myFunc() { }
    };
    

    我认为没有其他办法。对不起。

    【讨论】:

      【解决方案4】:

      您可以将其添加为 base 的成员并使其成为虚拟或纯虚拟函数。但是,如果使用此路由,您还应该在基类中添加一个虚拟析构函数,以允许成功销毁继承的对象。

      class base
      {
      public:
         virtual ~base(){};
         virtual void myFunc() = 0;
      };
      
      class derived : public base
      {
        public:
         derived() {}
         void myFunc() { cout << "My derived function" << std::endl; }
      
      };
      

      【讨论】:

      • 使其受到保护将无法从base* 调用该方法。
      猜你喜欢
      • 2021-09-09
      • 2013-03-04
      • 2017-08-02
      • 1970-01-01
      • 1970-01-01
      • 2013-09-23
      • 1970-01-01
      • 1970-01-01
      • 2014-08-11
      相关资源
      最近更新 更多