C++四种cast学习笔记

MirrorYuChen
MirrorYuChen
发布于 2024-12-31 / 6 阅读
0
0

C++四种cast学习笔记

C++四种cast学习笔记

1.static_cast

​ static_cast是一种更安全的转换方式,它在编译时检查转换的合法性。常见使用情形如下:

  • (1) 非多态类型转换:可用于替换C中强制类型转换,与此同时,编译器隐式执行的任何类型转换,都可以使用 static_cast显式完成,如整形和浮点型,void*于具体类型指针之间转换或非 const类型转换为 const类型;
#include <iostream>

int main(int argc, char *argv[]) {
  double x = 3.141592653589793;
  int y = static_cast<int>(x);
  float z = static_cast<float>(x);
  std::cout << "x: " << x << " y: " << y << " z: " << z << std::endl;
  {
    double *a = new double;
    void *b = static_cast<void*>(a);
    delete a;
  }
  
  return 0;
}
  • (2) 向上转换子类指针或引用转换为父类指针或引用,这种转换在类层次结构中是安全的;
  • (3) 向下转换父类指针或引用转换成子类指针或引用,这要求转换是合法的,即实际对象类型确实是目标子类类型,若不是,结果就是未定义的。
#include <iostream>

class Base {};

class Derived : public Base {};

int main(int argc, char *argv[]) {
  Base *a = new Base();
  Derived *b = new Derived();
  // 向上转换,安全的转换
  if (Base *x = static_cast<Base*>(b)) {
    std::cout << "a is a Base" << std::endl;
  }

  // 向下转换,不安全的转换
  if (Derived *y = static_cast<Derived*>(a)) {
    std::cout << "b is a Derived" << std::endl;
  }

  delete a;
  delete b;
  a = nullptr;
  b = nullptr;
  return 0;
}

​ 基类指针可以直接指向派生类对象,这个过程不需要显式转换。而能否合法转换,主要取决于二者间是否存在任一方向的隐式转换关系。

2.dynamic_cast

​ dynamic_cast多用于类层次结构中父类和子类之间指针和引用的转换,由于运行时类型检查,因此可以保证下行转换的安全性。

#include <iostream>

class Base {
public:
  virtual ~Base() {}
};

class Derived : public Base {
public:
  virtual ~Derived() {}
};

int main(int argc, char *argv[]) {
  Base *a = new Base();
  Base *b = new Derived();

  Derived *c = dynamic_cast<Derived*>(b);
  Derived &d = static_cast<Derived&>(*b);
  Derived &&e = static_cast<Derived&&>(*b);
  

  delete a;
  delete b;
  a = nullptr;
  b = nullptr;
  return 0;
}

3.const_cast

​ const_cast用于去除 constvolatile限定符,只针对指针(包括 this指针)和引用,大部分使用是将常量指针转换成常指针(常量指针指向空间内容不允许被修改,但使用 const_cast强制转换就可以修改)。

#include <iostream>
#include <string>

void Print(char *str) {
  std::cout << str << std::endl;
}

class A {
public:
  A() = default;
  ~A() = default;

  void Change(int value) const {
    // const_cast 用于移除const属性限定符
    const_cast<A*>(this)->value_ = value;
    std::cout << "value changed to " << value_ << std::endl;
  }

private:
  int value_;
};

int main(int argc, char *argv[]) {
  // 1.指针操作
  std::string str = "Hello, World!";
  // str.c_str()返回数据类型为const char *
  // 使用const_cast将const char *转换为char *
  Print(const_cast<char*>(str.c_str()));
  
  // const_cast不能修改基本类型
  // int *data = const_cast<int*>(str.c_str());  // 错误
  
  // 2.引用操作
  int a = 10;
  const int &b = a;
  int &c = const_cast<int&>(b);
  c = 20;
  std::cout << "a = " << a << std::endl;
  
  // 3.this指针
  A a{};
  a.Change(10);
  
  return 0;
}

​ 需要注意的是,const_cast只能转换类型限定符,不能修改基本类型

4.reinterpret_cast

​ 从字面意思来看为重新诠释转型,相当于C语言的强制转换,可用于任意指针(或引用)间转换,但不检查安全性,它只告诉编译器把指针从一种类型重新解释成另外一种类型。

#include <iostream>

int main(int argc, char *argv[]) {
  int i = 7;
  reinterpret_cast<unsigned int &>(i) = 42;
  std::cout << "i = " << i << std::endl;

  void *p = &i;
  int *ip = reinterpret_cast<int *>(p);
  *ip = 13;
  std::cout << "i = " << i << std::endl;

  return 0;
}

5.参考资料


评论