不带指针或引用的c++虚函数调用
c++ virtual function call without pointer or reference
据我所知,虚函数调用通常需要指针或引用。所以我对下面的代码感到非常惊讶。
#include <iostream>
using namespace std;
class B{
public:
void runB(){ call(); }
virtual void call(){ cout<<"Bn"; };
};
class D: public B{
public:
void runD(){ runB(); }
void call(){ cout<<"Dn"; }
};
int main(){
D d;
d.runD();
}
输出为
D有人能评论一下为什么这个虚函数调用是有效的吗?谢谢。
在成员函数中,任何对其他成员函数或变量的引用都通过this
指针隐式解析。在runB()
的定义中,call()
实际上是指this->call()
。虚函数调用使用当前对象的虚表执行。
首先,虚函数调用不需要指针或引用。就语言而言,任何对虚函数的调用都是虚调用,除非通过使用限定函数名显式地抑制虚分派机制。例如,这些
d.D::call(); // calls `D::call()` directly
d.B::call(); // calls `B::call()` directly
是显式强制为非虚的调用。然而,这
d.call(); // calls `D::call()` virtually
是虚调用。在这种情况下,对编译器来说,目标函数是D::call()
是显而易见的,因此编译器通常会将这个虚拟调用优化为常规的直接调用。然而,从概念上讲,d.call()
仍然是一个虚拟调用。
其次,在B::runB()
内部调用call()
是通过指针进行的。指针隐式地出现在这里。在B::runB()
里面写call()
只是(*this).call()
的简写。this
是指针。所以调用是通过一个指针进行的
第三,虚调用的关键属性是根据调用中使用的对象的动态类型选择目标函数。在您的例子中,即使在B::runB()
内部,对象*this
的动态类型也是D
。这就是为什么它调用D::call()
,因为它应该。
B::runB()
内部的(*this).call()
调用中观察到的。尽管*this
的静态类型是B
,但它的动态类型是D
,并且调用被分派到D::call()
。
虚拟与非虚拟的区别是:
不是虚的——总是按照调用者对象/引用/指针类型。
virtual - reference/pointer -按创建的对象类型执行。
virtual - object -由调用者处理。
例如:class A{
public:
virtual void f(){
cout <<"An";
}
};
class B: public A{
public:
virtual void f(){
cout <<"Bn";
}
};
B b;
A a,*pa=&b;
a.f(); //A: caller type = created type - same for not virtual
b.f(); //B: caller type = created type - same for not virtual
((A)b).f(); //A: object goes by the caller type - same for not virtual
pa->f(); // B: pointer goes by the created type - it would be A if it was not virtual!!
相关文章:
- 函数调用中参数的顺序重要吗
- 基于另一个成员参数将函数调用从类传递给它的一个成员
- 变量没有改变?通过向量的函数调用
- 在两个类中共享相同的函数调用,并在不需要时避免空实例化
- 是否有C++编译器选项允许激进地删除所有函数调用,并将参数传递给具有空体的函数
- 我知道函数调用中存在歧义.有没有办法调用foo()函数
- 模板函数调用
- 获取从C++中同一类中的构造函数调用的方法返回的值
- 析构函数调用
- 成员函数调用和C++对象模型
- 使用共享指针的函数调用,其对象应为 const
- C++:编译时检查匹配的函数调用对?
- 函数调用C++中的参数太少
- 来自 DLL 的函数调用 [表观调用的括号前面的表达式必须具有(指向-)函数类型]
- 返回指向对象的指针的函数调用是否为 prvalue?
- C++ 如何重载 [] 运算符并进行函数调用
- 代码的效率. 转到和函数调用
- 是同一作用域的函数部分中的函数调用
- 如何封装一个函数,以便它只能由同一类中的一个其他函数调用?
- 类型擦除的std::function与虚拟函数调用的开销