当前位置:  开发笔记 > 编程语言 > 正文

C++如果我将派生对象向上转换为其基类型,虚函数是否仍然有用

如何解决《C++如果我将派生对象向上转换为其基类型,虚函数是否仍然有用》经验,为你挑选了2个好方法。

考虑以下:

B继承自A并覆盖打印功能.

A有一个静态函数,它取一个void*,将它转换为A并调用虚拟打印函数.

如果void*最初是B,它会调用A :: print还是B :: print?

#include 

class A {
public:
        static void w(void *p) {

                A *a = reinterpret_cast(p);
                a->print();
        }

        virtual void print() {
           std::cout << "A"  << std::endl;
        }
};

class B : public A {

public:
        void print() {
           std::cout << "B"  << std::endl;
        }
};

int main () {
        B b;
        A::w(&b);
}

这为我打印B.

似乎已经转换为A的void*仍然知道B被覆盖的打印功能.原因不是立即清楚.

有人可以向我解释这是否是我可以依赖的行为,或者它是否只是一些有效的因为它是一个小例子(比如返回对局部变量的引用并不总是在小程序中段错误).



1> billz..:

您的代码具有未定义的行为

§5.2.10重新解释演员

7将"指向T1的指针"类型的prvalue转换为"指向T2的指针"类型(其中T1和T2是对象类型,T2的对齐要求不比T1更严格)并返回其原始类型会产生原始指针值.未指定任何其他此类指针转换的结果.



2> king_nak..:

虚函数通常由隐式求解vtable.这基本上是类层次结构中每个虚函数的函数指针数组.编译器将其添加为您的类的"隐藏成员".调用虚函数时,调用vtable中的相应条目.

现在,当您创建一个类型的类时B,它隐式地将B-vtable存储在对象中.强制转换不会影响此表.

因此,当你投射void *到时A,原始的vtable(类B)存在,指向B::print.

请注意,这是实现定义的行为,标准不保证这一点.但大多数编译器都会这样做


除了调用代码根据`A`的布局查找v表...并且不能保证它匹配'B`的布局.在许多情况下,它没有.(其他人提到了多重和虚拟继承,但标准并没有将布局差异限制为这两个原因)
这不是实现定义的,它只是未定义的.
推荐阅读
虎仔球妈_459
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有