【问题标题】:C++ : What is happening when a non-overridden calls a overridden method?C++:当非重写调用重写方法时会发生什么?
【发布时间】:2016-01-24 21:03:24
【问题描述】:
被调用的重写方法的版本取决于
如果您关心“通过”基类或“通过”派生类调用函数。但是,我发现如果我调用了一个非覆盖的方法,并且被覆盖的方法调用了一些 被覆盖的函数,那么即使我通过指针访问实例,仍会调用基类版本到派生类。有人可以解释为什么会这样吗?
代码:
class Base {
public:
void display() {
foo();
}
void foo() {
cout << "Base.foo()" << endl;
}
};
class Derived : public Base {
public:
void foo() {
cout << "Derived.foo()" << endl;
}
};
int main() {
Derived* derived = new Derived();
derived->display();
while (true) {}
}
【问题讨论】:
标签:
c++
overriding
member-hiding
【解决方案1】:
基类版本仍然被调用,即使我正在访问
通过指向派生类的指针来实例化。有人可以解释一下
为什么会这样?
虽然你通过派生类的指针调用方法,但你的方法不是虚拟的,所以使用静态调度,所以Base::display()直接调用Base::foo(),即使它在子类中被覆盖。为了实现你想要的行为,你必须使用动态调度,即将你的方法标记为virtual。
class Base {
public:
void display() {
foo();
bar();
}
void foo() {
cout << "Base.foo()" << endl;
}
virtual void bar() {
cout << "Base.bar()" << endl;
}
};
class Derived : public Base {
public:
void foo() {
cout << "Derived.foo()" << endl;
}
virtual void bar() {
cout << "Derived.bar()" << endl;
}
};
int main() {
Derived* derived = new Derived();
derived->display();
}
输出:
Base.foo()
Derived.bar()
【解决方案2】:
问题是:你没有重写任何函数;你有hidden its name。
在 C++ 中,只有虚函数(参见 C++ FAQ)可以被覆盖。将 Base::foo() 设为虚拟会产生预期的结果:(run code!)
class Base {
public:
void display() {
foo();
}
virtual void foo() {
cout << "Base.foo()" << endl;
}
};
class Derived : public Base {
public:
void foo() {
cout << "Derived.foo()" << endl;
}
};
int main() {
Derived* derived = new Derived();
derived->display();
}
【解决方案3】:
virtual qualifier needs to be used for methods that need to be overridden.
ex:
class Base {
public:
void display() {
foo();
}
virtual void foo() {
cout << "Base.foo()" << endl;
}
};
class Derived : public Base {
public:
virtual void foo() {
cout << "Derived.foo()" << endl;
}
};
int main() {
Derived* derived = new Derived();
derived->display();
while (true) {}
}
【解决方案4】:
您没有使用虚函数。
类层次结构中的对象有两种类型:它是“真正的”类,以及编译器当前认为它具有的类。
当你调用一个虚函数时,编译器总是调用属于“真实”类的函数。当你调用一个非虚函数时,编译器调用的函数属于它认为是对象类的类。
在子类中执行代码时,编译器认为 *this 是子类的对象。因此,调用非虚拟函数将调用属于该子类的函数。