【问题标题】:Calling derived class method in base class在基类中调用派生类方法
【发布时间】:2014-09-05 05:22:34
【问题描述】:

我们可以在派生类中调用“基类方法”。但是我们可以在基类函数中调用派生类方法吗?

#include<iostream.h>

class base {

 public:

   void print()
   {
     cout<<"base class";
   }

};

 class derived : public base

 {

  public:
    void print()
    {

            cout<<"derived class";

    }

 };

如何在基类中调用这个派生类print()函数?

【问题讨论】:

  • 您在寻找虚函数吗?
  • 基类对派生类一无所知。你的问题不正确。请尝试更正您的问题。

标签: c++ class inheritance base derived


【解决方案1】:

您不能从基类调用派生类中定义的正常方法。你可以做的是在基类中添加一个virtual(可能是纯的)方法,在派生类中提供实现。您可以从 base 调用此方法。

class Base{
public:
 virtual void foo(){cout<<"Hello";};
 void bar() { foo();}
};

class Derived: public Base{
 public:
 void foo() override{ cout<<"Hi";}
};

int main() {
 Base* b1 = new Derived();
 b1->bar(); //will call Derived::foo()

 Base* b2=new Base();
 b2->bar(); // will call Base::foo()
}

【讨论】:

  • +1 表示override。另一种可能的选择是 CRTP,但这可能太先进了......
【解决方案2】:

如果是虚拟方法,您可以从派生类对象的基类方法调用派生类的方法:

class base {
  public:
    void doSomething() { 
      print();  
    }
    virtual void print() {
      cout<<"base class";
    }
};

class derived : public base {
  public:
    virtual void print() {
      cout<<"derived class";
    }
};

int main() {
  derived d;
  base* pb = &d;
  pb->doSomething();
}

它被称为Template method pattern

【讨论】:

  • 这里的关键是print() 并不是真正的派生类方法;它在基类中声明,因此所有实例(基类或派生类)都必须具有它。派生类只是提供了不同的实现。
【解决方案3】:

如果您确定base 的所有实例化都将作为derived 的基类(使用Curiously Recurring Template Pattern 可能就是这种情况),您可以简单地static_cast thisderived*

#include <iostream>

class base {
public:
    void call_derived_print();
    void print()
    {
        std::cout<<"base class";
    }
};

class derived : public base
{
public:
    void print()
    {
       std::cout<<"derived class";
    }
};

void base::call_derived_print() {
    //undefined behaviour unless the most-derived type of `*this`
    //is `derived` or is a subtype of `derived`.
    static_cast<derived*>(this)->print();
}

【讨论】:

  • 对我来说这是不安全的。 Base::print 应该是纯虚拟,或者以正确的方式使用 CRTP。人们喜欢做各种各样的事情
  • @RakibulHasan:只要满足答案中列出的限制条件,它就是绝对安全的。有时您不想支付虚拟通话的费用。
  • 就是重点,满足约束就安全了,为什么要留坑呢?相反,您可以选择模板。
  • @RakibulHasan:由于basederived 显然只是虚拟名称,因此这里没有什么可以说这不会以正确的方式使用CRTP。已经有 4 个答案提到了 virtual 函数,我同意在大多数情况下这是一个更好的解决方案,所以似乎不需要另一个答案来谈论这些。这个答案是为了如果有一些约束要求print 是非虚拟的。
猜你喜欢
  • 2014-03-17
  • 2016-01-01
  • 2019-07-25
  • 2013-03-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-05-11
相关资源
最近更新 更多