C++ 11

003 类型别名

2020-02-02  本文已影响0人  赵者也

传统的定义别名的方法是使用关键字 typedef

typedef  double wages;  // wages 是 double 的同义词
typedef wages base, *p; // base 是 double 的同义词,p 是 double* 的同义词

新标准规定了一种新的方法,使用 别名声明 来定义类型的别名:

class CollegeStudents
{
public:
    CollegeStudents() {}
    // ...
};

using CS = CollegeStudents;

使用示例:

wages hours, weeks;
CS someone;

** 指针、常量和类型别名 **

如果某个类型别名指代的是复合类型或常量,那么把它用到声明语句里就会产生意想不到的后果。例如下面的声明语句用到了类型 pstring,它实际上是类型 char* 的别名:

typedef char * pstring;
const pstring nullstr0 = nullptr;
const pstring *ps;

上面两条声明语句的基本类型都是 const pstring,const 是对给定类型的修饰。pstring 实际上是指向 char 的指针,因此,const pstring 就是指向 char 的常量指针,而非指向常量字符的指针。
遇到一条使用了类型别名的声明语句时,乡亲们往往会错误地尝试把类型别名替换成它本来的样子,以理解该语句的含义:

const char * nullstr1 = nullptr;

然而,乡亲们,这种理解是错误的。声明语句中用到 pstring 时,其基本数据类型是指针。可是用 char * 重写了声明语句后,数据类型就变成了 char,* 成为了声明符的一部分。这样改写的结果是, const char 成了基本数据类型。前后两种声明含义截然不同,前者声明了一个指向 char 的常量指针,改写后的形式则声明了一个指向 const char 的指针。

使用如下代码测试 ps、nullstr0、nullstr1 的类型:

#include <QCoreApplication>
#include <cxxabi.h>
#include <QDebug>
#include <typeinfo>
#include <iostream>
#include <string>
#include <memory>
#include <cstdlib>

namespace  {

std::string demangle(const char* mangled)
{
      int status;
      std::unique_ptr<char[], void (*)(void*)> result(
        abi::__cxa_demangle(mangled, nullptr, nullptr, &status), std::free);
      return result.get() ? std::string(result.get()) : "error occurred";
}

template<class T>
void foo(T t) { std::cout << demangle(typeid(t).name()) << std::endl; }


typedef char * pstring;
const pstring nullstr0 = nullptr;
const pstring *ps;

const char * nullstr1 = nullptr;

}

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    foo(ps);
    foo(nullstr0);
    foo(nullstr1);

    return a.exec();
}

输出结果为:

char* const*
char*
char const*
上一篇 下一篇

猜你喜欢

热点阅读