C++之static_cast

cplusplus.com中的解释:

“static_cast can perform conversions between pointers to related classes, not only upcasts (from pointer-to-derived to pointer-to-base), but also downcasts (from pointer-to-base to pointer-to-derived). No checks are performed during runtime to guarantee that the object being converted is in fact a full object of the destination type. Therefore, it is up to the programmer to ensure that the conversion is safe. On the other side, it does not incur the overhead of the type-safety checks of dynamic_cast.

1
2
3
4
classBase {};classDerived:publicBase {};
Base * a =newBase;
Derived * b =static_cast<Derived*>(a);

This would be valid code, although b would point to an incomplete object of the class and could lead to runtime errors if dereferenced.
Therefore, static_cast is able to perform with pointers to classes not only the conversions allowed implicitly, but also their opposite conversions.
static_cast is also able to perform all conversions allowed implicitly (not only those with pointers to classes), and is also able to perform the opposite of these. It can:

  • Convert from void* to any pointer type. In this case, it guarantees that if the void* value was obtained by converting from that same pointer type, the resulting pointer value is the same.
  • Convert integers, floating-point values and enum types to enum types.

Additionally, static_cast can also perform the following:

  • Explicitly call a single-argument constructor or a conversion operator.
  • Convert to rvalue references.
  • Convert enum class values into integers or floating-point values.
  • Convert any type to void, evaluating and discarding the value.

从上面的内容来看,static_cast的功能还是很多的。记录重要的几点:

1. 相当于C语言的强制类型转换。如把int转成size_t:static_cast<size_t> i_value

2. 做基类的下行转换时,不安全,建议用dynamic_cast.

3. 用于基本数据类型之间的转换,如把int转换成char,把int转换成enum。

4. 把空指针转换成目标类型的空指针。

5. 把任何类型的表达式转换成void类型。

6. static_cast不能转换掉expression的const、volatile、或者__unaligned属性

C++之reinterpret_cast

在cplusplus.com中的解释如下:

reinterpret_cast converts any pointer type to any other pointer type, even of unrelated classes. The operation result is a simple binary copy of the value from one pointer to the other. All pointer conversions are allowed: neither the content pointed nor the pointer type itself is checked.

It can also cast pointers to or from integer types. The format in which this integer value represents a pointer is platform-specific. The only guarantee is that a pointer cast to an integer type large enough to fully contain it (such as intptr_t), is guaranteed to be able to be cast back to a valid pointer.

The conversions that can be performed by reinterpret_cast but not by static_cast are low-level operations based on reinterpreting the binary representations of the types, which on most cases results in code which is system-specific, and thus non-portable.

大意是说主要用于指针类型的转换,以及指针与足够大的整数类型之间的转换;从整数类型(包括枚举类型)到指针类型,无视大小。比特位不变。安全性由程序员自己保证

判断大小端及字节交换

之前写过一篇“如何判断机器的CPU是大端还是小端?http://www.orangespeech.com/?p=89”的blog, 现在更新一下开源代码中的简洁实现:

int IsLittleEndian() {
int check = 1;
  return (*reinterpret_cast<char*>(&check) != 0);
}

C的实现如下:

 #define BIG_ENDIAN      0
 #define LITTLE_ENDIAN   1

  int little_endian(void)
  {
      short int w = 0x0001;
      char *byte = (char *) &w;
      return(byte[0] ? LITTLE_ENDIAN : BIG_ENDIAN);
  }

顺带给出字节交换的代码,同样厉害!

#define SWAP8(a) { \
  int t = ((char*)&a)[0]; ((char*)&a)[0]=((char*)&a)[7]; ((char*)&a)[7]=t;\
      t = ((char*)&a)[1]; ((char*)&a)[1]=((char*)&a)[6]; ((char*)&a)[6]=t;\
      t = ((char*)&a)[2]; ((char*)&a)[2]=((char*)&a)[5]; ((char*)&a)[5]=t;\
      t = ((char*)&a)[3]; ((char*)&a)[3]=((char*)&a)[4]; ((char*)&a)[4]=t;}
#define SWAP4(a) { \
  int t = ((char*)&a)[0]; ((char*)&a)[0]=((char*)&a)[3]; ((char*)&a)[3]=t;\
      t = ((char*)&a)[1]; ((char*)&a)[1]=((char*)&a)[2]; ((char*)&a)[2]=t;}
#define SWAP2(a) { \
  int t = ((char*)&a)[0]; ((char*)&a)[0]=((char*)&a)[1]; ((char*)&a)[1]=t;}

纯虚类与dynamic_cast

今天看到一段代码,用dynamic_cast将每个vector的成员cast到基类。但是,如果基类是一个纯虚类,似乎没有这个必要。以下是我的实验:

#include <iostream>
#include <vector>

using namespace std;

class Father{
        public:
                virtual void get()=0;
};
class Son: public Father{
        public:
                void get(){ cout<<"Son"<<endl;}
};

class Daughter: public Father{
        public:
                void get() {cout<<"Doughter"<<endl;}
};

int main(){

        vector<Father *> a;

        Son s1;
        a.push_back(&s1);
        Daughter d1;
        a.push_back(&d1);

        for(size_t i=0;i<a.size();i++){
            //Father *ts = dynamic_cast<Father *>(a[i]);
            //ts->get();
            a[i]->get();//可以获得与上两行一样的结果
        }
        return 0;
}

最近读到《资治通鉴》上一段话,觉得说得太好了,摘抄下来,供今后慢品。

 “夫信者,人君之大宝也。国保于民,民保于信;非信无以使民,非民无以保国。是故古之王者不欺四海,霸者不欺四邻,善为国者不欺其民,善为家者不欺其亲。不善者反之,欺其邻国,欺其百姓,甚者欺其兄弟,欺其父子。上不信下,下不信上,上下离心,以至于败。所利不能药其所伤,所获不能补其所亡,岂不哀哉!”

回忆

若干年后,我们将如何回忆这样一场变故?从个人的角度,谈一谈对于许多事情的看法。
对于生命,多一份珍惜与敬畏。科技发达的今天,一个病毒足以摧毁整个医疗系统,生命变得如此脆弱。如果不好好珍惜,逝去有时很轻易。如果不多一份敬畏,生命的休止符常常来得悄无声息。
对于善与美,多一份感动与感激。那些战斗在一线的人,他们可以是出于职责,可以是出于号召,但不能不被他们感动。安宁的日子里,都不过是平凡角色的扮演者;在这些特殊的日子,他们站在了第一线,为我们筑起防线,保卫了我们的健康与安宁。
对于丑与恶,多了一份不耻与严厉。无论身居何位,无论影响大小,图一己之私利,于公众利益而不顾,更有甚者,趁火打劫,为非做歹,常叹良知何在!
对于未来,多了一份期待与信心。经过这一场变故,我们才会发现,安居乐业的日子不容易,才是真真切切的幸福。我们也会发现那些需要改进的地方,只有做得更好,更完善,才能抵御风浪,才能有实实在在的幸福!