0

我有以下片段:

#include <iostream>

using namespace std;

class IA 
{
    public:
    virtual void printA() = 0;
    virtual ~IA(){};
};

class IB 
{
    public:
    virtual void printB() = 0;
    virtual ~IB(){}
};

class IC : public IA, public IB 
{
    public:
    void printA() {cout << "hello world a" << endl; }
    void printB() {cout << "hello world b" << endl; }
};

void func(IB* p)
{
    p->printB();
}

int main()
{
    IA* p = new IC;
    p->printA();
    cout << "cast to ib" << endl;
    func((IB*)p);
    return 0;
}

执行代码后,我得到以下结果:

hello world a  
cast to ib 
hello world a

我的问题是,编译器对(IB*)p那个原因func调用做了什么,p->printB()但得到的是结果hello a而不是hello b

演员幕后是什么??什么编译器生成用于转换?如果我更改为func(dynamic_cast<IB*>(p)),则得到print b正确的结果。

4

1 回答 1

5

(IB*)preinterpret_cast<IB*>(p)然而,here 确实会产生一个无效的指针,因为IAandIB不相关。

dynamic_cast<IB*>(p)做正确的事是因为它检查对象的 typeinfo*p并发现该对象派生了IAIB并返回一个经过适当调整的指向 的IB子对​​象的指针IC。请注意,IA指针与指向 object 的指针一致IC,不像IB

struct IA {
    virtual ~IA(){};
};

struct IB {
    virtual ~IB(){}
};

struct IC : IA, IB {};

int main() {
    IA* p = new IC;
    std::cout << "IA: " << p << '\n';
    std::cout << "IB: " << dynamic_cast<IB*>(p) << '\n';
    std::cout << "IC: " << dynamic_cast<IC*>(p) << '\n';
}

输出:

IA: 0x21c1c20
IB: 0x21c1c28
IC: 0x21c1c20

C 风格转换如何在 C++ 中工作的完整信息:显式类型转换

当遇到 C 风格的转换表达式时,编译器会尝试将其解释为以下转换表达式,顺序如下:

  1. const_cast<new_type>(expression);
  2. static_cast<new_type>(expression), 带有扩展:即使基类不可访问(即,此转换忽略私有继承说明符),还允许将派生类的指针或引用转换为指向明确基类的指针或引用(反之亦然)。同样适用于将指向成员的指针转换为指向明确非虚基成员的指针;
  3. static_cast(带扩展名)后跟const_cast;
  4. reinterpret_cast<new_type>(expression);
  5. reinterpret_cast其次是const_cast。选择满足相应强制转换运算符要求的第一个选项,即使它无法编译。如果转换可以以多种方式解释为 static_cast 后跟 const_cast,则无法编译。此外,允许 C 风格的转换表示法在指向不完整类类型的指针之间进行转换。如果两者expressionnew_type都是指向不完整类类型的指针,则未指定是否选择static_castreinterpret_cast

请注意,C 风格的案例永远不会dynamic_cast.

C 风格的强制转换在 C++ 中被认为是不好的做法,因为当类型和层次结构发生变化时,它们的含义会默默地改变。为健壮的代码使用 C++ 强制转换。

于 2018-12-04T11:17:25.457 回答