我想知道动态调度在C++中到底是如何工作的。为了说明我的问题,我将从一些Java代码开始。
class A
{
public void op(int x, double y) { System.out.println("a"); }
public void op(double x, double y) { System.out.println("b"); }
}
class B extends A
{
public void op(int x, double y) { System.out.println("c"); }
public void op(int x, int y) { System.out.println("d"); }
}
class C extends B
{
public void op(int x, int y) { System.out.println("e"); }
}
public class Pol
{
public static void main(String[] args)
{
A a = new C();
B b = new C();
/* 1 */ a.op(2, 4);
/* 2 */ b.op(2.0, 4.0);
}
}调用a.op(2, 4)将打印"c",因为实际上编译器:
A (因为a被声明为A类型的变量),哪个方法最接近op(int, int),op(int, int)方法,但找到方法op(int, double) (使用单个自动转换int -> double),在执行过程中,JVM:
op(int, double)修复到类C中的方法,但没有找到,B,op(int, double),然后调用它。同样的原则也适用于调用b.op(2.0, 4.0),它打印"b“。
现在,考虑一下C++中的等效代码
#include <iostream>
class A
{
public:
virtual void op(int x, double y) { std::cout << "a" << std::endl; }
virtual void op(double x, double y) { std::cout << "b" << std::endl; }
};
class B : public A
{
public:
void op(int x, double y) { std::cout << "c" << std::endl; }
virtual void op(int x, int y) { std::cout << "d" << std::endl; }
};
class C : public B
{
public:
void op(int x, int y) { std::cout << "e" << std::endl; }
};
int main()
{
A *a = new C;
B *b = new C;
/* 1 */ a->op(2, 4);
/* 2 */ b->op(2.0, 4.0);
delete a;
delete b;
}a->op(2, 4)会像Java一样打印"c“。但是b->op(2.0, 4.0)再次输出"c“,在那里,我迷路了。
在C++中编译和执行动态调度时究竟应用了哪些规则?(注意,如果在每个函数前面编写virtual,您将从virtual代码中得到相同的行为;这里没有任何变化)
发布于 2013-09-20 09:32:35
对于C++,当您执行b->op(2.0, 4.0);时,编译器在B中查找一个方法,它可以调用(int x, double y)并使用它。如果子类中有任何方法能够处理调用,则不查看超类。这叫做方法隐藏。op(double, double)是隐藏的。
如果要使其选择(double x, double y)版本,则需要在B中使用以下声明在B中使该函数可见
using A::op;进一步解释“规则”
发布于 2013-09-20 09:34:05
通过在op中声明一个新的重载到B,您已经隐藏了基本版本。编译器将只根据'B‘进行分派,这就是它选择op(int,double)的原因。
发布于 2013-09-20 10:22:16
如果您告诉编译器,编译器会在转换时发出警告/错误。使用gcc,编译器参数-Wconversion -Werror将阻止您的代码编译,因为您是对的,在这里有一个潜在的精度损失。
考虑到您没有打开此编译器选项,编译器很乐意将对b->op(double,double)的调用解析为B::op(int,double)。
请记住,这是一个编译时决策--而不是运行时/多态决策。
"b“指针的实际vtable在运行时将有一个方法op(int,int)可用,但是编译器在编译时不知道这个方法。它只能假定b指针的类型为B*。
https://stackoverflow.com/questions/18913202
复制相似问题