Sta*_*ack 3 c++ polymorphism binding
假设没有 Hello 函数,我们只是在 main 中调用 ob.display ,然后它调用 B 类而不是 A 类的显示函数。
函数 display() 的调用由编译器设置为基类中定义的版本一次。这称为函数调用的静态解析,或静态链接——函数调用在程序执行之前就被固定。这有时也称为早期绑定,因为 display() 函数是在程序编译期间设置的。
现在如何在基类中的显示函数之前不使用 virtual 关键字(后期绑定)来调用派生类的显示函数?
现在,在这个程序中,将对象作为按值调用、按指针调用和按引用调用 Hello 函数进行传递都可以正常工作。现在,如果我们使用多态性并希望在调用派生类的成员函数时显示它,我们必须在基类中的显示函数之前添加 virtual 关键字。如果我们通过指针调用和引用调用来传递对象值,它会调用派生类中的函数,但如果我们通过值传递对象,则不会,为什么会这样?>
class A
{
public:
void display(); // virtual void display()
{
cout << "Hey from A" <<endl;
}
};
class B : public A
{
public:
void display()
{
cout << "Hey from B" <<endl;
}
};
void Hello(A ob) // &ob //*ob
{
ob.display(); // ob->display()
}
int main()
{
B obj;
Hello(obj); // obj //&ob
return 0;
}
Run Code Online (Sandbox Code Playgroud)
现在如何在基类中的显示函数之前不使用 virtual 关键字(后期绑定)来调用派生类的显示函数?
非虚函数只是由编译器根据调用它的对象(或引用或指针)的静态类型来解析。因此,给定一个派生类型的对象以及对其子对象的引用:
B b;
A & a = b;
Run Code Online (Sandbox Code Playgroud)
调用非虚函数会得到不同的结果:
b.display(); // called as B
a.display(); // called as A
Run Code Online (Sandbox Code Playgroud)
如果您知道真实类型,那么您可以指定要调用该版本:
static_cast<B&>(a).display(); // called as B
Run Code Online (Sandbox Code Playgroud)
但如果引用的对象a没有 type ,那就会出现严重错误B。
现在,如果我们使用多态性并希望在调用派生类的成员函数时显示它,我们必须在基类中的显示函数之前添加 virtual 关键字。
正确的。如果将函数设为虚拟函数,则即使您使用不同类型的引用或指针来访问它,它也会在运行时根据对象的动态类型进行解析。所以上面的两个例子都将其称为B.
如果我们通过指针调用和引用调用来传递对象值,它会调用派生类中的函数,但如果我们通过值传递对象,则不会,为什么会这样呢?
如果您按值传递它,那么您将对其进行切片:仅复制A对象的一部分,以创建 类型的新对象A。因此,无论该函数是否是虚拟的,在该对象上调用它都会选择版本A,因为它A只是一个A.
如果您通过引用或指针传递,那么您仍然可以访问原始对象及其动态类型B。因此,虚拟函数调用将解析为该B版本。
| 归档时间: |
|
| 查看次数: |
1787 次 |
| 最近记录: |