派生类的基类调用方法?

时间:2014-04-09 17:55:04

标签: c++ inheritance

class BaseClass {
 public:
  virtual void method1(){
   method2();
  };
  virtual void method2(){
   std::cout << "Base Method" << std::endl;
  };
}

class DerivedClass : public BaseClass {
 virtual void method2(){
   std::cout << "Derived Method" << std::endl;
  };
}

int main() {
  DerivedClass derived;
  derived.method1();
}

在上面的示例中,我将“派生方法”作为输出 - 为什么会发生这种情况?

我了解DerivedClass继承自BaseClass,因此derived可以致电method1,但我不明白为什么method2来自DerivedClassmethod2调用BassClass时隐藏BaseClass

对任何糟糕的代码/错误表示歉意 - 对C ++来说还是新手。

4 个答案:

答案 0 :(得分:3)

因为method2virtual

当你将一个函数声明为virtual时,你真正做的是使它通过指针或引用(换句话说,以正常方式)调用该函数时实际上调用的是派生最多的重载。

这是一件好事,通常正是你想要的。请注意,从您拨打电话的上下文来看并不重要。您可以从基类的上下文中调用method2,该基类的实现可用method2。据推测,你假设自从你从基类调用基类&#39;实现是将要调用的实现。

这不是virtual的工作方式 - 而且这也是一件好事。

如果您愿意,可以通过明确它来调用基类中的版本:

class BaseClass {
 public:
  virtual void method1(){
   BaseCLass::method2();
  };

但这通常是不可取的,而且在我的书中,有一种代码味道。

答案 1 :(得分:2)

derived.method1()静态绑定函数调用BaseClass::method1(),但此函数调用虚函数method2()。这会导致动态绑定到DerivedClass::method2(),而不是调用BaseClass::method2()

如果要在BaseClass::method2()中静态绑定BaseClass::method1(),则必须执行以下操作:

class BaseClass {
 public:
  virtual void method1(){
   BaseClass::method2(); //explicit class scope prevents dynamic binding
  }
  virtual void method2(){
   std::cout << "Base Method" << std::endl;
  }
};

答案 2 :(得分:0)

因为你宣称它是虚拟的。如果您不想要这种行为,请删除虚拟声明。虚拟化对于继承和面向对象编程的整个概念至关重要。请参阅&#34; C ++编程语言(特别版)&#34;第12章进行深入讨论。

答案 3 :(得分:0)

尝试从virtual的{​​{1}}中删除method2()个关键字。 这将为您输出&#34; 基本方法&#34;。这是静态绑定,并且BaseClass的{​​{1}}被调用,method1调用BaseClass也是如此。

相反,虚拟成员函数是动态解析的(在运行时)。也就是说,基于对象的类型动态地(在运行时)选择成员函数。因此,method2的对象将始终仅调用派生类的BaseClass,输出将为&#34; 派生类&#34;。