dynamic_cast更改原始对象

dynamic_cast changes original object?

本文关键字:原始 对象 cast dynamic      更新时间:2023-10-16

为什么dynamic_cast<new>(old)会改变old

示例代码:

#include <iostream>
#include <string>
class MyInterface {
public:
  virtual void say() = 0;  
  virtual ~MyInterface() { }
};
class SubInterface : public MyInterface {
public:
  std::string test = "test";
  virtual void say() = 0;
  virtual ~SubInterface() { }
};
class Example : public SubInterface { 
public:
  void say() {
    std::cout << test << std::endl;
  } 
}; 

int main() {
  MyInterface* ex1 = new Example(); 
  SubInterface* ex2 = dynamic_cast<SubInterface*>(ex1);
  if (ex2 != nullptr) {
    std::cout << "call ex2->say(): ";
    ex2->test = "something else";
    ex2->say();
  }
  else { 
    std::cout << "error" << std::endl;
  }
  std::cout << "call ex1->say(): ";
  ex1->say();
  std::cerr << "debug: ex1=" << ex1 << "; ex2=" << ex2 << std::endl;
  return 0;
}

哪些输出:

call ex2->say(): something else
call ex1->say(): something else
debug: ex1=0xf1e010; ex2=0xf1e010

所以我期望ex2ex1不同,因此希望ex2->test = "something else";不会改变ex1。我想这是有意的行为,但为什么呢?(如果它们没有不同,为什么甚至有必要为dynamic_cast的结果分配任何东西?(人们可以继续使用ex1

任何帮助,不胜感激。

我想这是有意的行为,但为什么呢?

您正在将指针强制转换为其他类型,而不是创建新对象。两者都指向同一个Example对象;一个把它当作MyInterface,另一个把它当作SubInterface。因此,通过一个指针修改对象后,对它的更改可以通过另一个指针可见,因为两者都指向同一对象。

如果它们没有不同,为什么甚至有必要为dynamic_cast的结果分配任何东西?

它们不一定相同。使用多重继承时,不同的基类子对象可能位于整个对象中的不同位置。在这种情况下,向下强制转换可能必须调整指针值以指向整个对象。

人们可以继续使用ex1

不。即使像您一样,它确实具有相同的值,它也具有错误的类型。它声明指向MyInterface,它没有test成员,所以你不能说ex1->test

ex1 和 ex2 指向同一个对象,但类型不同。 换句话说,内存是相同的(相同的示例对象(,但如何操作内存是通过两个不同的接口(MyInterface或子接口(完成的。

dynamic_cast 是一个运行时强制转换,可用于通过不同于另一个变量类型所允许的不同(相关(接口安全地操作数据。 这有很多用途,尽管您的示例当然不需要它。

dynamic_cast所做的只是另外验证指向对象的实际类型是否与您期望的类型匹配,如果不匹配,则返回nullptr。如果它们确实匹配,它将返回指向同一对象的指针,就好像您进行了static_cast一样(形象地说,除了运行时检查之外还有其他一些细微的差异(。此附加验证不会创建新对象。 dynamic_cast没有改变对象——你改变了。

Dynamic_cast永远不会更改原始对象,在您的例子中为"ex1"。最初分配的内存保持不变。否则,您将遇到各种泄漏和内存损坏。

您的意图似乎也是了解它是否可以为您提供与输入指针不同的指针。

要理解这一点,您必须在两个方向上进行推理 - 向上转换和向下转换以及继承和成员变量等。

在这个问题上,其他人有很好的答案。建议搜索相关的。