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
来自DerivedClass
从method2
调用BassClass
时隐藏BaseClass
。
对任何糟糕的代码/错误表示歉意 - 对C ++来说还是新手。
答案 0 :(得分:3)
因为method2
是virtual
。
当你将一个函数声明为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;。