compile-time 和运行时期间的虚拟和 non-virtual 函数 (C++)
Virtual and non-virtual functions during compile-time and runtime (C++)
希望标题不会混淆。我试图理解以下由在 C++ 中定义 class virtual 或 not 的方法引起的问题。假设我有一个基数 class A 和一个派生的 class B,这样
class A {
public:
void print() { cout << "A"; }
}
class B : A {
public:
void print() { cout << "B"; }
}
如果我知道执行下面的代码,打印命令将打印出 "A"。
A *a = new A();
B *b = new B();
((A *)b)->print(); // this prints "A"
但是,如果我在两个 class 中都将 "print" 方法声明为虚拟方法,我会看到 "B" 打印在我的屏幕。为什么会发生这种情况?
如果函数不是 virtual
,编译器将只使用表达式给出的任何类型。因此,当您将 B
对象转换为 A
对象时,它将调用 A::print
函数。
如果使用virtual
,编译器会构建table个函数指针[1],当要调用函数时,编译器生成代码通过那个table,而不是仅仅查看当前类型,它允许基类型调用派生 class 中的函数,从而允许多态行为。
[1] 从技术上讲,规范没有告诉我们如何实现它,但几乎所有编译器都是这样工作的。如果编译器可以使用魔术产生相同的行为,则允许这样做 - 只要魔术是可靠且可重现的。
A * b = 新 B(); //LHS 是编译时 = RHS 是运行时(因为'对象是在运行时创建的)
B.print();
if print is non virtual:
编译时间: A.print() 解析为开始工作(因为它是一个真实的函数)
运行时:A.print() 是 deployed/dispatched 工作。
如果 print 是虚拟/非真实函数:
编译时间:绕过 A.print() 并解决 B.print去上班
运行时:B.print() 是 deployed/dispatched 工作。
希望标题不会混淆。我试图理解以下由在 C++ 中定义 class virtual 或 not 的方法引起的问题。假设我有一个基数 class A 和一个派生的 class B,这样
class A {
public:
void print() { cout << "A"; }
}
class B : A {
public:
void print() { cout << "B"; }
}
如果我知道执行下面的代码,打印命令将打印出 "A"。
A *a = new A();
B *b = new B();
((A *)b)->print(); // this prints "A"
但是,如果我在两个 class 中都将 "print" 方法声明为虚拟方法,我会看到 "B" 打印在我的屏幕。为什么会发生这种情况?
如果函数不是 virtual
,编译器将只使用表达式给出的任何类型。因此,当您将 B
对象转换为 A
对象时,它将调用 A::print
函数。
如果使用virtual
,编译器会构建table个函数指针[1],当要调用函数时,编译器生成代码通过那个table,而不是仅仅查看当前类型,它允许基类型调用派生 class 中的函数,从而允许多态行为。
[1] 从技术上讲,规范没有告诉我们如何实现它,但几乎所有编译器都是这样工作的。如果编译器可以使用魔术产生相同的行为,则允许这样做 - 只要魔术是可靠且可重现的。
A * b = 新 B(); //LHS 是编译时 = RHS 是运行时(因为'对象是在运行时创建的)
B.print();
if print is non virtual:
编译时间: A.print() 解析为开始工作(因为它是一个真实的函数)
运行时:A.print() 是 deployed/dispatched 工作。
如果 print 是虚拟/非真实函数:
编译时间:绕过 A.print() 并解决 B.print去上班
运行时:B.print() 是 deployed/dispatched 工作。