在派生对象上调用基函数

calling a base function on a derived object

class base{
   public:
   virtual void foo(){
     std::cout << "base::foo was called" << std::endl;;
   }
 
   void bar(){
     foo();
     std::cout << "base::bar was called" << std::endl;;
   }
};

class derived : public base {
  public:
  void foo() {
    std::cout << "derived::foo was called" << std::endl;
  }
};

int main() {
    derived der;
    der.bar();
    // desired output = "base::foo was called" "base::bar was called"
    // actual output = "derived::foo was called" "base::bar was called"

}

我是不是遗漏了什么明显的东西?
为什么 bar() 函数在派生 class 的对象上调用时调用 derived::foo 函数,即使该函数本身仅存在于基础 class.[=13= 中]

base::foo 声明为 virtual,因此使用虚拟分派。如果你不想那样,那么明确地调用 base::foo

struct  base{
   virtual void foo(){
     std::cout << "base::foo was called" << std::endl;;
   }
 
   void bar(){
     base::foo();
     std::cout << "base::bar was called" << std::endl;;
   }
};

(请注意,在您的示例中所有方法都是私有的,我想那只是一个错字)

当派生 class 中的成员函数重写 基 class 中的虚拟成员函数时,这意味着它完全替换了函数大多数目的的定义。因此,在 main 中创建的对象 der 上调用函数 foo 通常会使用 Derived::foo 定义。无论调用 foo 的代码是在 Derived 的成员中还是在 Base 的成员中,或者两者都不在 class.

中,此行为是一致的

两个主要的例外是:

  1. 如果您使用“qualified-id”class_type::func_name 语法来调用该函数,将禁用虚函数逻辑并仅调用您命名的函数(在正常名称查找和重载解析之后)。

既然你说你想让程序调用 base::foo,那么把 base::bar 改成:

void bar() {
    base::foo();
    std::cout << "base::bar was called" << std::endl;
}
  1. 在基类 class 的构造函数或析构函数期间,将调用基类 class(或其基类之一)中的函数,忽略派生 class 中的覆盖程序(西)。该对象被认为还不是或不再是派生类型的对象。 (如果派生函数被调用并使用任何尚未创建或已经销毁的派生成员,这将是麻烦。)

当您声明一个函数 virtual 时,编译器将为每个创建的对象生成一个 vtable,在您的情况下,由于该对象是一个 derived 函数 [=对于该实例,11=] 将始终指向 derived::foo()