文档章节

Effective C++: static_cast, const_cast

SHIHUAMarryMe
 SHIHUAMarryMe
发布于 2016/01/29 23:12
字数 902
阅读 153
收藏 6

const_cast<new_type>(expression):

 

直接看demo吧:

#include <iostream>
 
struct type {
    type() :i(3) {}
    void m1(int v) const {
        // this->i = v;                 // compile error: this is a pointer to const
        const_cast<type*>(this)->i = v; // OK as long as the type object isn't const
    }
    int i;
};
 
int main() 
{
   //case 1:
    int i = 3;                    // i is not declared const
    const int& cref_i = i; 
    const_cast<int&>(cref_i) = 4; // OK: modifies i
    std::cout << "i = " << i << '\n';
 
    //case 2:
    type t; // note, if this is const type t;, then t.m1(4); is UB
    t.m1(4);
    std::cout << "type::i = " << t.i << '\n';
 
    //case 3:
    const int j = 3; // j is declared const
    int* pj = const_cast<int*>(&j);
    *pj = 4;         // undefined behavior!
 
   //case 4:
    void (type::*mfp)(int) const = &type::m1; // pointer to member function
//  const_cast<void(type::*)(int)>(mfp); // compiler error: const_cast does not
                                         // work on function pointers
}

 

static_cast<new_type>(expression): 返回一个new_type类型的值.

1,Notice: 此时的new_type是既不是指针(pointer)也不是任何引用(reference)的情况.

如果 expression 和 new_type之间存在一个隐式(implicit)的转换关系(比如: int->double, short int->int..., 甚至是如果一个类类型(class)含有operator Type()我们都能完成从 expression 到 new_type的转换,或者是一个class含有一个implicit的构造函数此时我们相当于用expression构造该class),转换后返回的是一个 new_type类型的右值(rvalue).

2,Notice: 此时的new_type是一个类类型(class)的指针(pointer)或引用(reference),expression则是一个new_type的非虚基类的情况.

注意如果new_type是指针的话,传递进来的expression必定也是指针类型的变量,此时在static_cast内部会进行是否是nullptr的检查,如果是引用的话这不会检查。

无论是引用还是指针此时static_cast的最终目的都是从 基类(base-class)向派生类(derived-class)的转换.

3,Notice: 此时的new_type是一个右值引用类型(比如:int&&, std::vector<int>&&),此时expression可以是左值可以是右值.

当把一个lvalue(左值)转为右值(rvalue)的时候其实相当于对expression调用了std::move;

4,Notice: 此时的new_type为void;

当我们有一个不用的参数的时候编译器会经过就可以调用static_cast<void>(expression);消除编译器警告.

5,Notice: 取回存于void*指针的,原类型的指针.

6,Notice: 此时new_type为enum类型.

把一个enum(不管有没有指定class)类型的值转为它的underlying-type;

把一个指定了class的enum的类型转为一个没有指定class的enum类型.

7,如果一个指针指向派生类的成员(不管是数据成员,还是成员函数),且该成员是通过继承得到的也就是说该成员其实是基类中的那么我们可以通过static_cast,把该指针转为指向基类的该成员的指针.

8,指向任何类型的指针都能转为 void*;

 

#include <vector>
#include <iostream>
 
struct B {
    int m = 0;
    void hello() const {
        std::cout << "Hello world, this is B!\n";
    }
};
struct D : B {
    void hello() const {
        std::cout << "Hello world, this is D!\n";
    }
};
 
enum class E { ONE = 1, TWO, THREE };
enum EU { ONE = 1, TWO, THREE };
 
int main()
{
    // 1: initializing conversion
    int n = static_cast<int>(3.14); 
    std::cout << "n = " << n << '\n';
    std::vector<int> v = static_cast<std::vector<int>>(10);
    std::cout << "v.size() = " << v.size() << '\n';
 
    // 2: static downcast
    D d;
    B& br = d; // upcast via implicit conversion
    br.hello();
    D& another_d = static_cast<D&>(br); // downcast
    another_d.hello();
 
    // 3: lvalue to xvalue
    std::vector<int> v2 = static_cast<std::vector<int>&&>(v);
    std::cout << "after move, v.size() = " << v.size() << '\n';
 
    // 4: discarded-value expression
    static_cast<void>(v2.size());
 
    // 5. inverse of implicit conversion
    void* nv = &n;
    int* ni = static_cast<int*>(nv);
    std::cout << "*ni = " << *ni << '\n';
 
    // 6. array-to-pointer followed by upcast
    D a[10];
    B* dp = static_cast<B*>(a);
 
    // 7. scoped enum to int or float
    E e = E::ONE;
    int one = static_cast<int>(e);
    std::cout << one << '\n';
 
    // 8. int to enum, enum to another enum
    E e2 = static_cast<E>(one);
    EU eu = static_cast<EU>(e2);
 
    // 9. pointer to member upcast
    int D::*pm = &D::m;
    std::cout << br.*static_cast<int B::*>(pm) << '\n';
 
    // 10. void* to any type
    void* voidp = &e;
    std::vector<int>* p = static_cast<std::vector<int>*>(voidp);
}

 

 

 

© 著作权归作者所有

共有 人打赏支持
SHIHUAMarryMe
粉丝 12
博文 162
码字总数 136638
作品 0
武汉
程序员
C++ Primer 学习笔记(第四章:表达式)

C++ Primer 学习笔记(第四章:表达式) [TOC] 4.1 基础 左值和右值: 当一个对象被用作右值的时候,用的是对象的值(内容);当对象被用作左值的时候,用的是对象的身份(在内存中的位置)。...

ShawnLue
2015/08/20
0
0
线程局部存储空间 pthread_key_t、__thread 即 ThreadLocal

线程局部存储空间 pthreadkeyt、_thread 即 ThreadLocal thread 参考: 线程局部变量 _thread 关键字 thread是GCC内置的线程局部存储设施,thread变量每一个线程有一份独立实体,各个线程的值...

呆呆的张先生
08/30
0
0
对malloc的返回值应该如何转型

本文概括叙述了一篇老文的内容,并且总结对malloc返回值的3种转型方式,(相对于原文)更全面的总结其各自的应用范围。 1. 原文内容 2. 对malloc的3种转型方式 3. 各自的应用范围 以前有篇文...

Start-up
2012/05/08
0
0
[从C到C++] 1.7 C++ 强制类型转换

[toc] 在C++语言中新增了四个关键字staticcast、constcast、reinterpretcast和dynamiccast。这四个关键字都是用于强制类型转换的。我们逐一来介绍这四个关键字。 1) static_cast 在C++语言中...

wu_being
06/16
0
0
C++的四种新式显示转换和一种旧式显示转换

C++的四种新式显示转换和一种旧式显示转换 1、静态转换(static_cast) static_cast包含的转换类型有典型的非强制变换、窄化(有信息丢失)变换、使用void*的强制转换、隐式类型 变换、类层次...

扬名立万
2014/07/23
0
0

没有更多内容

加载失败,请刷新页面

加载更多

【挑战剑指offer】系列03:逆序打印单链表

本系列的算法原题来自于“牛客网-剑指offer”,写这个板块,不仅仅是解决算法问题本身,更是手动提高难度、自行变式,思考更多的解决方案,以带给自己一些启发。 1. 【逆序打印单链表】原始题...

LinkedBear
44分钟前
2
0
Linux内存布局

今天这篇文章主要是我之前看Linux内核相关知识和博客Gustavo Duarte中。我主要是看了这篇博客,并且结合之前的知识,对内存管理的的理解又上升了一个档次。所以想通过这篇文章总结下。 我们先...

linuxprobe16
今天
1
0
day94-20180921-英语流利阅读-待学习

记录死亡还是消费死者?自杀报道的媒体偏见 雪梨 2018-09-21 1.今日导读 自杀事件报道一直是新闻报道的重要部分,具有骇人听闻、吸引眼球的特点。可是在报道这些事件的时候,除了客观陈述事实...

飞鱼说编程
今天
4
0
如何通过 J2Cache 实现分布式 session 存储

做 Java Web 开发的人多数都会需要使用到 session (会话),我们使用 session 来保存一些需要在两个不同的请求之间共享数据。一般 Java 的 Web 容器像 Tomcat、Resin、Jetty 等等,它们会在...

红薯
今天
5
0
C++ std::thread

C++11提供了std::thread类来表示一个多线程对象。 1,首先介绍一下std::this_thread命名空间: (1)std::this_thread::get_id():返回当前线程id (2)std::this_thread::yield():用户接口...

yepanl
今天
4
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部