您的位置:首页 > 编程语言 > C语言/C++

C++(2)基本数据类型

2015-08-07 18:27 495 查看


变量和基本类型

引言:

1、各种程序设计语言都具有许多各具特色的特征,这些特征决定了用每种语言适合开发哪些类型的应用程序。

2、大多数现代现代程序设计语言都采用两种方式扩充语言的基本特征集:允许程序员通过自定义数据类型扩充该语言;提供一组库例程,这些例程定义了一些并非内置在语言中的实用函数和数据类型。

3、C++是静态类型语言,支持在编译时执行类型检查。

4、包括C++在内的其他语言允许程序员定义的类型不仅有数据还包含操作!

5、掌握C++的第一步就是学习语言的基本知识和标准库!

6、类型可以告诉我们:数据代表什么意思;可以对数据执行哪些操作。

正文:


一、基本内置类型

1、算术类型的存储空间大小依机器而定。

2、wchar_t类型用于扩展字符集,如汉字,日文等。

3、 1字节=8位

1B = 8bit

1字/word= 32b/4B

P31的《内置类型和机器级表示》非常重要,值得细读!

一般的,short类型为半个机器字长,int为一个机器字长,而long为2个机器字长(在32位操作系统中int与long通常字长是相同的!)

4、虽然char有三种不同的类型,但是只有两种表示方式。

5、一般,float类型用一个字长表示,double用两个字长表示,而long double要用三个或四个字长来表示。

类型的取值范围决定了浮点数所含的有效数字位数。如果没有特殊要求,一般推荐使用double!

6、P33《建议:使用内置算术类型》值得一读!


二、字面值常量

只有内置类型存在字面值,没有类类型的字面值!

1、在char类型字面值前面加L就得到了wchar_t类型的宽字符字面值,如:

wchar_t A = L'A';

2、转义字符可以通过'\'符号来表示,如:

\ooo 三个八进制数字表示字符的数字值

\xddd 十六进制数字表示字符的数字值

3、字符串字面值连接

[cpp] view
plaincopy





//正确:

std::cout << "A multi-line "

"string literal "

"using concatenation"

<< std::endl;

std::cout << "Who goes with F\145rgus?\012"

<< std::endl;

//错误:

std::cout << "A multi-line " L "string literal " "using concatenation" << std::endl;

std::cout << 3.14UL << std::endl;

4、多行字面值

[cpp] view
plaincopy





std::cout << "A multi-line " "string \

literal " "using concatenation"

<< std::endl;

P37

[cpp] view
plaincopy





//习题2.10

#include <iostream>



int main()

{

std::cout << "\062\115\n"

<< "\062\t\115\n"

<< std::endl;

return 0;

}


三、变量

P38

[cpp] view
plaincopy





//习题2.11

#include <iostream>



int main()

{

std::cout << "Please input the base and the exponent:" << std::endl;

int base,exponent;

std::cin >> base >> exponent;



int result = 1;

for (int i = 0;i < exponent; ++i)

{

result *= base;

}

std::cout << result << std::endl;



return 0;

}

1、C++是一门静态类型语言,在编译时会作类型检查;静态类型检查机制能够帮助我们更早的发现错误。

2、变量提供了程序可以操作的有名字的存储区。变量的类型决定了变量的内存大小和布局,能够存储在该内存中的值的取值范围以及可应用在该变量上的操作集。

3、什么是对象:对象就是内存中具有类型的区域。(P40)

4、标识符不能包含两个连续的下划线,也不能以下划线开头后跟一个大写字母。

5、变量命名习惯:

1)变量名一般小写。

2)标识符应使用帮助记忆的名字。

3)包含多个词的标识符书写在每个词之间添加一个下划线。

4)命名习惯最重要的是保持一致!

P41

[cpp] view
plaincopy





//习题2.14

char _; //错误

bool catch-22; //错误

char 1_or_2 = '1'; //错误

float Float = 3.14; //正确

6、定义对象

[cpp] view
plaincopy





//可以以逗号分开的含有一个或者多个说明符列表

//类型决定了分配给变量的存储空间大小和可以在其上执行的操作集合。

double sales_price,avg_price;

1)初始化

C++支持两种格式的初始化:

a.复制初始化:int ival = 1024; //有多个初始化式时不能使用复制初始化!

b.直接初始化:int ival(1024); //直接初始化的方法更灵活且效率更高

【在C++中:初始化并不就是赋值:初始化是创建变量并给他赋值,赋值是擦除对象的当前值并且用新值代替】

2)初始化多个变量:

正确:double salary = 9999.99,wage(salary + 0.01);

P44

[cpp] view
plaincopy





//习题2.15

//该语句是错误的,既然指定mouth,day用八进制来初始化,就不要用数字'9'

int mouth = 09,day = 07;



//习题2.16

//该语句正确

double wage = 10;

double salary = wage = 15;

3)变量初始化规则

a.内置类型的变量是否初始化取决于变量定义的位置:在函数体外定义的变量都初始化成0,在函数体内定义的内置类型变量不进行自动初始化。

【但是,未初始化的变量事实上都有一个值】

建议:每个内置类型的对象都要初始化。

b.类通过定义一个或多个构造函数来控制类对象的初始化。如果一个类有默认构造函数,则无论变量在哪儿定义,默认构造函数都会被调用。

4)声明和定义

C++通过extern关键字声明,向程序表明变量的类型和名字。因为extern是声明,所以不分配存储空间。

一个变量可以声明多次,但只能定义一次

如果声明有初始化式,那么它可以被当作是定义,即使有声明标记extern,如:

[cpp] view
plaincopy





extern double PI = 3.14; //只有当extern声明位于函数外部时,才可以含有初始化式,但是有些编译器还是不能通过编译。

5)名字的作用域

大多数的作用域是通过花括号来定界的。

C++作用域可嵌套:

[cpp] view
plaincopy





//在函数内定义一个与函数可能会用到的全局变量同名的局部变量总是不好的,局部变量最好使用不同的名字!

#include <iostream>

#include <string>



std::string s1 = "hello"; // s1 has global scope



int main()

{

std::string s2 = "world"; // s2 has local scope



// uses global s1; prints ``hello world''

std::cout << s1 << " " << s2 << std::endl;



//int类型的s1将屏蔽掉std::string类型的s1

int s1 = 42; // s1 is local and hides global s1



// uses local s1; prints ``42 world''

std::cout << s1 << " " << s2 << std::endl;

return 0;

}

6)在便零使用处定义变量

通常把一个对象定义在他首次使用的地方是一个很好的方法!

P48

[cpp] view
plaincopy





//习题2.20下列程序会输出什么?

#include <iostream>



int main()

{

int i = 100,sum = 0;

for (int i = 0;i != 10; ++i)

{

sum += i;

}



std::cout << "i = " << i << ", sum = " << sum << std::endl;

return 0;

}

//答案:i = 100, sum = 45


四、const限定符

[cpp] view
plaincopy

#include <iostream>



int main()

{

//for循环语句存在两个问题

for (int index = 0;index != 512; ++index)

{

//...

}

return 0;

}

/*

*1、程序的可读性:存在魔数512[魔数:他的意义在上下文中并没有体现出来,好像这个数是魔术般变出来的]

*2、程序的可维护性...

*/

1、定义const对象

[cpp] view
plaincopy

//bufSize此时是一个左值,但是现在这个左值不可修改!

const int bufSize = 512;

因为常量在定义之后就不能修改,所以定义时就必须初始化!

2、const对象默认为文件的局部变量

除非特殊说明,在全局作用域中声明的const变量是定义该对象的文件的局部变量,此变量只存在于那个文件中,不能被其他文件访问!

如若想被其他文件访问,需要在const前加extern关键字!

[cpp] view
plaincopy

//file_1.cc

extern const int bufSize = 512;



//file_2.cc

extern const int bufSize;

for (int index = 0;index != bufSize; ++index)

{

//...

}

【说明:】非const对象默认为extern。而const对象默认为非extern,要使const变量能够在其他的文件中访问,必须显式指定它为extern。

P50

[cpp] view
plaincopy

//习题2.23(b)下列语句是否正确

int cnt = 0;

const int sz = cnt;

五、引用

引用的主要作用是用作函数的形式参数。

1、下列语句是否正确

[cpp] view
plaincopy

int ival = 1024; //正确

int &refVal_1 = ival; //正确

int &refVal_2 = refVal_1; //正确

int &refVal_3; //错误

2、当引用初始化之后,主要该引用存在,他就保持绑定到初始化时的对象,不能将引用绑定到另外一个对象!

初始化是指定引用指向哪个对象的唯一方法!

3、const引用[指向const对象的引用]

[cpp] view
plaincopy

/*

*仅仅允许const应用绑定到需要临时变量作为媒介来完成完全绑定过程的值

*因为const引用是只读的,即:

*非const引用只能绑定到与该引用相同类型的对象,

*const引用则可以绑定到不同但相关的类型的对象或绑定到右值。

*理解下面程序:

*/

int ival = 1024;

const int &refVal_1 = 1024;

const int &refVal_2 = ival;

// int &refVal_3 = refVal_2;



int i = 42;

const int &r = 42;

const int &r2 = r + i;



double dval = 3.14;

const int &refDval = dval; //如果int前的const去掉对不对呢?

P52

[cpp] view
plaincopy

//习题2.25,判断下列程序的输出结果

#include <iostream>



int main()

{

int ival = 2.01;

int &rval2 = ival;

const int &rval3 = 1;

rval2 = rval3;

++ rval2;

std::cout << rval3 << std::endl;

return 0;

}

六、typedef

typedef用开定义类型的同义词

[cpp] view
plaincopy

typedef double wages;

typedef wages salary;

//typedef定义以关键字typedef开始,后面是数据类型和标识符,标识符或类型名并没有引入新的类型,而至是现有的数据类型的同义词。

typedef通常被用于以下三种目的:

1、为了隐藏特定类型的实现,强调使用类型的目的

2、简化复杂的类型定义,使其更易理解

3、允许一种类型用于多个目的,同时使得,每次使用该类型的目的明确


七、枚举

枚举不但定义了整数常量集,而且还把它们聚集成组; 枚举与简单的const常量相比孰优孰劣, 通过下面一段代码, 一看便知:

[cpp] view
plaincopy





enum {input, output, append};



const int input = 0;

const int output = 1;

const int append = 2;

1、定义并初始化枚举

[cpp] view
plaincopy





//默认地,第一个枚举成员赋值为0,后面每个枚举成员赋的值比前一个大1.

enum open_modes{input,output,append};

2、枚举成员是常量

用来初始化枚举成员的值必须是一个常量表达式,常量表达式是编译器在编译时就能够计算出结果的整数表达式。

枚举成员值可以是不唯一的:

[cpp] view
plaincopy





enum Points {point2d = 2,point2w,

point3d = 3,point3w

};

Points a = point3w; //正确

Points a = 4; //错误


八、类类型

C++中,通过类来自定义数据类型。类定义了该类型的对象包含的数据和该类型的对象可以执行的操作。

1、从操作开始设计类

在定义类时,通常是先定义类的接口,即该类所提供的操作,通过这些操作,可以决定该类完成其功能所需要的数据,以及是否需要定义一些函数来支持该类的实现。

定义Sales_item类:

[cpp] view
plaincopy





class Sales_item

{

public:

//...



private:

std::string isbn;

unsigned units_sold;

double revenue;

};//不要忘记分号

2、public与private访问标号控制类的成员在类外是否可以访问。

3、类的数据成员定义了该类类型对象的内容。

4、一般,不能把类成员的初始化作为其定义的一部分!!!

5、类的成员函数可以使用类的任何成员,而不管其访问权限。而不是类的组成部分的代码不能访问private成员!

6、用class和struct关键字定义类的唯一区别在于默认访问级别!

[cpp] view
plaincopy





//P57 习题2.28,编译下列程序,注意出错信息

class Foo

{

//empty

}



int main()

{

return 0;

}


九、编写自己的头文件

为了实现程序可以由多个文件组成,C++支持分别编译!

1、头文件一般包含:类的定义,extern变量声明和函数的声明

2、头文件的正确使用能够带来的好处:

1)能够保证所有文件使用给定实体的同一个声明。

2)当声明需要修改时,只有头文件需要修改。

P58《编译和链接多个源文件》非常好,值得一读。

3、头文件用于声明而不是定义

例外情况:

1)头文件可以定义类

2)值在编译时就已知的const对象

3)inline函数

【这些实体可以在多个文件中定义,只要每个源文件中的定义是相同的】

4、一些const对象定义在头文件中

1)const变量默认是定义在该变量的文件的局部变量,因此,允许const变量定义在头文件中。

而且,常量表达式是编译器在编译的时候就能够计算出结果的表达式。

2)在实践中,大部分的编译器在编译时都会用相应的常量表达式来替换这些const变量的使用,所以,在实践中,不会有任何的存储空间用于存储用常量表达式初始化的const对象。

3)如果const对象不是用常量表达式初始化的,那么他就不应该在头文件中定义。相反的,他的变量就应该和其他变量一样,在源文件中定义并初始化。而应该在头文件中添加extern生命,以使其能够被多个文件共享。

[cpp] view
plaincopy





//P60习题2.32 下列哪些语句应该放在源文件中,哪些引该放在头文件中?

int var;

const double PI = 3.1415926;

extern int total = 255;

const double sq = squt(2.0);

5、避免多重包含

1)、在设计头文件时,应该使其可以多次包含在同一个源文件中。我们必须保证多次包含同一个头文件不会应其该头文件的定义的类和对象被多次定义。通常我们需要使用头文件保护符(header guard)

2)、#define表示接受一个名字并定义改名作为预处理器变量

3)、为了保证头文件在更定的源文件中只处理过一次,我们首先检测#ifndef,如果预处理器未定义,那么跟在其后的所有指示都会被处理,直到#endif,如果#ifndef发现SALESITEM_H已经定义,那么程序会忽略该头文件的剩余部分。

4)、头文件应该含有保护符!

5)、我们可以用定义在头文件里面的实体(如类)来命名处理器变量来避免处理器变量重名的问题!

[cpp] view
plaincopy





#ifndef SALESITEM_H

#define SALESITEM_H

//...

#endif // SALESITEM_H

6、使用自己的头文件

[cpp] view
plaincopy





/*

* 标准头文件,编译器将会在预定义的位置来查找该头文件,

*当然该位置可以通过设置设置查找路径变量或者通过命令行选项来修改

*/

#include <standard_header>

/*

*如果文件名包含在””中,表名是非系统头文件,

*非系统头文件的查找通常开始于源文件所在路径

*/

#include "my_file.h"

本文借鉴:http://blog.csdn.net/column/details/zjf666.html?&page=6
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: