dynamic_cast的行为上升了另一个链

tej*_*jas 1 c++

我只是在这里阅读这个问题 /sf/answers/23246051/ 它告诉动态演员

你可以使用它而不仅仅是向下投射 - 你可以侧身或甚至向上投射另一个链.dynamic_cast将寻找所需的对象并在可能的情况下返回它.

那么这究竟意味着什么呢?这种情况发生的限制/条件是什么?

我认为这就是声明的含义.演员阵容发生了,我也得到了一个明显的分段错误.

#include <iostream>
class base
{
public:
    virtual void print () = 0;
};

class childa : public base
{
public:
    char c1;
    virtual void print ()
    {
        std::cout << "childa\n";
    }
    void printout()
    {
        std::cout << "childa out\n";
    }
};

class childb : public base
{
public:
    int c2;
    virtual void print ()
    {
        std::cout << "childb\n";
    }
    void printin()
    {
        std::cout << "childb in\n";
    }
    void printout()
    {
        std::cout << "childb out\n";
    }
};

int main()
{
    base* b = new childa;
    b ->print();
    dynamic_cast<childa*>(b)->printout();
    dynamic_cast<childb*>(b)->printout();   // cast happens here and the output is printed
    dynamic_cast<childa*>(b)->c1 = 'a';
    dynamic_cast<childb*>(b)->c2 = 2;   // segfault here
}
Run Code Online (Sandbox Code Playgroud)

这是我得到的输出并且发生了段错误

childa
childa出
childb出

进程返回-1073741819(0xC0000005)执行时间:5.844 s
按任意键继续.

编辑:是的,我不检查空值是多么愚蠢.但我想更多地了解其他问题的评论(上/下/侧面)

Rei*_*ica 5

你在这里遇到未定义的行为:

dynamic_cast<childb*>(b)->printout();
Run Code Online (Sandbox Code Playgroud)

强制转换实际上失败了(返回空指针).您永远不会检查返回值并通过它调用成员函数.这是未定义的行为,任何事情都可能发生.在你的情况下,似乎因为函数不this以任何方式访问,即使通过空指针调用它也会执行得很好.但这并不能保证.


至于横向演员(或者演绎另一个链)是什么,需要更复杂的继承层次来证明:

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

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

struct child1 : base1
{};

struct child2 : base2
{};

struct both : child1, child2
{};


int main()
{
  child1 *c1 = new both();
  static_cast<base1*>(c1);  // ok
  static_cast<both*>(c1);  // ok
  static_cast<child2*>(c1);  // compile-time error, unrelated types
  dynamic_cast<child2*>(c1);  // succeeds, because the object is actually of type `both`, i.e. derived from `child2`; cast sideways
  static_cast<base2*>(c1);  // compile-time error, unrelated types
  dynamic_cast<base2*>(c1); // succeeds, because the object is actually of type `both`, i.e. derived from `base2`; cast up another chain

  base1 *b1 = new child1();
  static_cast<child1*>(b1);  // ok
  static_cast<both*>(b1);  // compiles, but produces UB, as the object is not of correct type
  static_cast<base2*>(b1);  // compile-time error, unrelated types
  dynamic_cast<base2*>(b1);  // fails (returns null pointer), because the object is not actually derived from `base2`.
}
Run Code Online (Sandbox Code Playgroud)