为什么这个静态C++转换工作?

mcA*_*ar2 10 c++ casting

想象一下这段代码:

class Base {
 public:
  virtual void foo(){}
};

class Derived: public Base {
  public:
    int i;
    void foo() override {}
    void do_derived() {
      std::cout << i;
    }
};

int main(){
  Base *ptr = new Base;
  Derived * static_ptr = static_cast<Derived*>(ptr);
  static_ptr->i = 10;  // Why does this work?
  static_ptr->foo(); // Why does this work?
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

为什么我在控制台上获得结果10?我想知道因为我认为ptr是指向基础对象的指针.因此,该对象不包含int i或方法do_derived().是否自动生成了一个新的derived-Object?

当我do_derived()在Base类中声明一个虚方法时,会选择这个,但为什么呢?

Snp*_*nps 25

int* i = new int{1};
delete i;
std::cout << *i << std::endl;
Run Code Online (Sandbox Code Playgroud)

如果工作的定义是代码将编译和执行,那么这也将"起作用".

但是,它显然是未定义的行为,并且无法保证可能发生的情况.


在您的情况下,代码编译为static_cast不执行任何检查,它只是转换指针.访问尚未分配和初始化的内存仍然是未定义的行为.


Ric*_*ges 8

正如评论中所提到的,"恰好按照预期行事"与"作品"不同.

我们做一些修改:

#include <iostream>
#include <string>

class Base{
public:
    virtual  void foo(){
        std::cout << "Base::foo" << std::endl;
    }
};

class Derived: public Base{
public:
    int a_chunk_of_other_stuff[1000000] = { 0 };
    std::string s = "a very long string so that we can be sure we have defeated SSO and allocated some memory";
    void foo() override {
        std::cout << "Derived::foo" << std::endl;
    }
    void do_derived() {
        std::cout << s << std::endl;
    }
};

int main(){
    Base *ptr = new Base;
    Derived * static_ptr = static_cast<Derived*>(ptr);
    static_ptr -> foo(); // does it though?
    static_ptr -> do_derived(); // doesn't work?
    static_ptr->a_chunk_of_other_stuff[500000] = 10;  // BOOM!
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

样本输出:

Base::foo

Process finished with exit code 11
Run Code Online (Sandbox Code Playgroud)

在这种情况下,没有一项操作符合我们的预期.分配到阵列导致了段错误.