《C++ Primer》读书笔记第二章-3-处理类型 And 自定义数据结构

来源:互联网 发布:联盟挂机软件下载 编辑:程序博客网 时间:2024/05/11 19:19

笔记会持续更新,有错误的地方欢迎指正,谢谢!

处理类型

类型别名

类型别名是某种类型的同义词,它让复杂的类型名字变得简单。
有两种方法用于定义类型别名:
1.传统的方法:typedef double two;
2.新方法:使用别名声明:using SI=Sales_item;

—-指针和谁都有一腿,既然有了个新东西,那指针又要来搞事情了
例子:
typedef char *test;
const test str1 = 0;
const char *str2 = 0;
这里的两个str一样吗? 不一样!
原因:str1是指向char的指针常量(《C++Primer》上为常量指针),str2 是指向const char的指针。当我们typedef了test 之后,test 本身已经作为一个基本数据类型无法分割了,所以const test str1这句话理解的时候,应该把test 当成int之类的来理解,这样const就是顶层的,说明它本身是常量。

第一种类型说明符:auto类型说明符(万能)

让编译器通过初始值推算变量类型,并赋诸该值。
例子:
auto a = b; //在不清楚b是什么类型的情况下,用auto,编译器会帮我们分析b的类型

//注意,auto一般会忽略顶层const,但保留底层const
//也就是说忽略本身是常量,保留所指的对象是常量
const int ci = i; //顶层const
const int &cr = ci; //底层const
auto b =ci; //b是int,忽略了顶层const
auto c = cr; //c是int,虽然cr是底层const,但cr只是ci的别名,ci本身是顶层const
auto d = &i; //d是整型指针
auto e = &ci; //对常量对象取地址是底层const,所以e是指向整型常量的指针

如果强行希望推断出的auto类型是顶层const,需要明确指出
const auto f = ci; //ci的推断类型是int,等价于const int f = ci。

看一下引用的情况,设置类型为auto引用时,初始值中的顶层const属性仍然保留:
auto &g = ci; //g是整型常量引用
auto &h = 42; //错误:42推断出int,等价于 int &h = 42,非常量引用去引用常量,违法
const auto &j = 42; //可以,常量引用去引用常量

第二种类型说明符:decltype类型指示符

我们使用auto可以万能,但我们不知道具体是什么类型,比如
auto a = b; //肯定合法,但是你知道a是啥类型吗
于是,C++设计者们又搞了个好东西,函数decltype,它的作用是返回操作数的数据类型。

decltype类型指示符的定义:让编译器通过初始值推算变量类型,但不用该初始值赋值。包含顶层const。赋值产生的引用、解引用、(())都会判为引用类型。
1.decltype返回其包含的函数的返回值类型
decltype(Func()) sum=x;//sum的类型就是函数Func()的返回值的类型

2.decltype返回其包含的变量的类型(包括顶层const和引用在内)
const int ci = 0, &cj = ci;
decltype(ci) x = 0; //,所以,x的类型是const int
decltype(cj) y = x; //y的类型是const int &,绑定到x
decltype(cj) z; //错,z是个引用,必须初始化

3.decltype返回其包含的表达式的结果类型
int i = 42, *p = &i, &r = i;
decltype(r+10) b; //正确:加法表达式,结果为int
decltype(*p) c; //错误:解引用表达式,结果类型为int&,则函数返回引用,但引用未被初始化。

4.特殊:
decltype(i) d; //正确,decltype使用的是一个不加括号的变量i,则得到的结果就是该变量i的类型以定义d。
decltype((i)) e; //错误,decltype使用的是一个加了括号的变量,编译器就是把此括号当作表达式,则得到的结果就是引用类型,即int&。
总结(记住结论就好):decltype((i)) 的结果永远是引用,而decltype(i)只有当i本身是引用的时候才是引用。

自定义数据结构

定义

自定义数据结构以关键字class(或struct)开始,紧跟着类名和实体,最后的分号不能省略。

类数据成员

定义了类的对象的具体内容,每个对象有自己的一份数据成员拷贝。修改一个对象的数据成员,不会影响其他对象。

头文件

通常包含那些只能被定义一次的实体,如类、const变量和constexpr变量等。
问题:头文件存在多次包含的情况(直接和间接),编译器会把头文件中的内容拷贝到包含文件中,而我们又要确保头文件中的内容不被多次定义。
解决方法:头文件保护符
例子:

#ifndef SALES_DATA_H  #define SALES_DATA_H  #include <string>//补充:#include<string>只搜索系统目录;而include"string"还要搜索编译器当前目录,肯定能搜到想要的头文件。但效率不同。struct Sales_data  {      //省略    //省略};  #endif
  • 预处理器:在编译前执行的一段程序,功能有:1.替换#include的头文件,2.头文件保护符避免重复定义实体。
  • 预处理器在这里发挥了很大的作用。 预处理命令#ifndef 是“如果没有定义”的意思,常和 预处理命令#endif 搭配使用,SALES_DATA_H是“预处理变量”(大写,#define将一个名字设置为预处理变量)。如果没有定义SALES_DATA_H,定义SALES_DATA_H,执行下面的代码直到#endif;如果SALES_DATA_H已经定义过,则后面的代码不会执行。这样确保头文件被多次包含时,其中的内容不会被多次定义。
阅读全文
0 0