使用多态指针调用函数
calling to functions with polymorphic pointers
#include <iostream>
class A{};
class AA:public A{};
struct X {
void f(A *) {
std::cout << "X::f(A*)n";
}
};
struct Y:public X {
void f(A *) {
std::cout << "Y::f(A*)n";
}
};
int main() {
Y *y = new Y();
X *x = new Y();
const X *cx = new Y();
y->X::f(new AA);
x->f(new AA);
}
打印:
X::f(A*(
X::f(A*(
我不明白为什么y->X::f(new AA)
和x->f(new AA)
不会引发编译错误。我知道在这两种情况下都调用了X::f(A *)
。但是编译器选择使用此方法的原理是什么?多态性函数过载?有什么经验规则吗?
你的问题意味着你期望在 X 中声明 f 是虚拟时你会得到的行为。 在某些语言中,这是唯一可能的行为。 C++你有一个选择。
正如您声明的 f 所示,它使用编译时类型,因此x-f(new AA)
调用X::f
因为x
是一个X*
如果您在 X 中声明了 f virtual,则x-f(new AA)
将调用 Y::f
,因为 x 指向 Y
对于问题的另一个方面(为什么为 Y 类型的对象调用 X::f 不涉及错误(,X 是 Y 的基类,因此应该有一个 X 类型的有效对象埋在 Y 类型的每个对象中,并且该 X 对象应该可用于任何 X 方法。
在看到上面的评论之前,我错过了您问题的第三个方面,即当您将AA*
传递给需要A*
的方法并且A
是AA
的基类时,编译器会推断出需要从AA*
到A*
的隐式强制转换。 该推导在很大程度上与 X::f 和 Y::f 之间的编译时或运行时选择无关
如果你这样做,你的代码目前是这样的:
y->X::f(new AA);
y->f(new AA);
x->f(new AA);
你会得到这个:
X::f(A*)
Y::f(A*)
X::f(A*)
但是,如果您将X::f
声明为虚拟,则会得到以下内容:
X::f(A*)
Y::f(A*)
Y::f(A*)
此外,由于 AA
是 A
的子类,因此可以将指针传递到AA
需要指向A
的指针的位置。
让x->f(new AA)
调用Y::f()
,那么你需要将X::f()
声明为virtual.
如果X::f()
没有声明为 virtual
,则(因为x
是一个X
指针(x->f(new AA)
调用X::f()
。
请参阅C++标准第 10.3 节"虚拟功能"(N3242(:
虚函数支持动态绑定和面向对象编程。声明或 继承的虚函数称为多态类。
如果虚拟成员函数
vf
在类Base
和类Derived
中声明,则直接或间接派生 从Base
开始,一个成员函数vf
与声明的名称、参数类型列表、CV 限定符和 refqualifier(或不存在相同(Base::vf
,则Derived::vf
也被virtual
(无论是否如此声明(并覆盖Base::vf
。
- 如何用参数值调用函数(仅在运行时已知)
- 从python中调用C++函数并获取返回值
- 当使用通配符和null指针调用函数时,对输出的说明
- 从R调用C++函数并对其进行集成时出错
- 使用QTreeView,如何通过调用函数只突出显示特定的行/列
- 如何在qt中从另一个类调用函数
- 在 COUT 语句中使用 COUT 调用函数
- 如何从线程中的不同模块调用函数?
- C++从函数指针数组调用函数
- 当 A 在 for 循环中调用函数 B 时,如何计算函数 A 的空间复杂度?
- 如何在 C/C++ 中从外部库调用函数
- 如何使用运算符在同一行中多次调用函数
- 是否可以创建一个从不同类调用函数的线程?
- 无法为类成员调用函数
- 如何从另一个标头 c++ 调用函数
- C++有什么方法可以在既不调用函数模板也不提供其模板参数的情况下引用函数模板?
- 如何只允许在调用函数 B 后调用函数 A?
- 我可以这样调用函数吗?
- 如何在 c++ 的类中递归调用函数方法?
- 为什么在指向对象的迭代器上调用函数不允许我更改对象本身?