1、第一个C++程序
一、文件扩展名
C++源代码的文件扩展名.cpp、C、cxx、c(须要指定编译语言)
自定义的头文件依然保留.h
二、头文件
C++标准库的头文件不带.h,最经常使用的是iostream
C语言中的头文件依然能够继续使用,stdio.h或cstdio
三、输入输出
cout<<输出
cin>>输入
endl换行
cout和cin再也不使用占位符,它能够自动识别数据类型。
scanf和printf能够继续使用。
四、编译器
gcc也能够编译C++的源码,但须要添加额外的参数
g++是编译C++源码的最简单的编译器,通常操做没有默认安装。
ubuntu系统的安装指令:sudo apt-get install g++
以前的gcc的编译参数,依然能够继续使用。
注意:C++编译时的错误提示不是很精准,一个错误可能会产生大量的错误提示。
五、引入了名字空间概念
using namespace std;
2、C++中的基本数据类型
一、C++彻底兼容C语言中的全部数据类型(C++兼容C语言的全部语法。)。
二、添加了bool类型、字节宽度1,数值true(非零值),false(零值)。
三、在显示bool变量前,使用boolalpha能够以true或flase的形式显示bool值。
四、void* 与其它类型指针的转换受到限制
void* 不能够直接给其它类型的指针赋值,必须通过强制转换。
任意类型的指针均可以直接给void*赋值。
3、C++中的联合、枚举、结构
一、在C++中联合、枚举、结构设计成功后,再使用不须要加关键字。
二、枚举的检查更为严格(C++中的枚举是一种独立的数据类型)。
三、结构成员中能够有函数,在函数中能够直接访问结构的成员。
四、结构对象能够继续使用.或->访问成员、成员函数。
五、结构中的成员添加了访问属性:
public:开放的,被它修饰过的成员在任何位置均可以访问
private:私有的,被它修饰过的成员只能在成员函数中使用
protected:之后再说。
六、结构在建立时会自动调用一个函数-构造函数。
a、无返回值
b、名字与结构相同
c、参数能够任意
七、结构在释放时会自动调用一个函数-析构函数。
a、无返回值、参数
b、~结构名
练习:C++的走迷宫。
4、引用
一、引用就起"外号",为一个标识符另外再取一个名字。
二、引用必需初始化,不然编译错误。
三、引用不光能够引用标识符,也能够引用当即数(右值、字面值、常量),但必须加const属性。
四、不能定义空引用,但"野引用"或"悬空引用"是存在的(引用了堆内存的数据,当堆内存释放后就不该该再使用)。
五、引用只能是一次性的,没法再更改(引用一旦成功后,它是个变量了这个身份至死不渝)。
六、引用能够看成函数的参数,它引用的对象就是函数的实参,因此引用能够达到指针的效果。
a、函数之间共享变量
b、提升参数的传递效率(比指针还要高)
c、能够获取参数
注意:能使用引用就不要再使用指针了。
引用可否彻底取代指针,不能够。
七、引用也能够看成函数的返回值,但毫不能返回局部变量的引用。
练习1:使用引用定义一个能够交换两人个变量值的函数。
练习2:定义一个函数,计算两个整数的最大公约数和最小公倍数,最大公约数使用返回值返回,最小公倍数使用引用返回。
5、C++中的内存管理运算符
一、在C++中使用 new/delete 来管理内存,new用来申请内存,delete用来释放内存。
二、new在内存时容许对内存进行初始化。
三、使用new建立结构对象时会自动调用构造函数,delete时会自动调用析构函数。
总结:malloc/free与new/delete的区别?
一、malloc/free标准库的函数,使用时还须要添加头文件,而new/delete是C++语言中的运算符。
二、malloc返回值的是void*指针,new返回的是有类型的指针。
三、malloc建立对象时不会调用构造函数,free时不会调用析构函数,但new/delete会自动调用构造和析构函数。
四、使用malloc使用内存时须要本身计算字节数,而使用new的时候会自动计算。
四、[]能够配合new和delete申请或释放数组。
new[]与不能够与delete混用,必须使用delete[]释放。
使用new[]/delete[]建立多少个对象就会调用屡次构造和析构。
五、new/delete与malloc/free不能混用。
六、delete不能够重复释放,但能够释放空指针。
七、若是使用new申请内存失败会抛出异常"std::bad_alloc",异常的捕获和处理会在之后讲解。
6、C++中的函数
一、C++中函数能够在main前执行,C语言中不能够。
二、C++中的函数名能够相同,只要参数不一样便可(函数重载,不仅是参数)。
函数能够同名并非真正意义上的同名,它只在编译基本把函数的名字添加了额外信息(函数的参数),返回值不算内。
三、内联函数
内联函数就是把函数编译成二进制,而后在须要的位置直接把函数拷贝过去,而不是跳转后再执行,这样能够减小进栈、出栈、和调用,以此提升程序的执行效率,但这样会增长可执行文件的大小。
内联函数与宏函数的区别:从本质上来讲它们是同样的,但内联函数能够检查参数,也能够具备返回值。
inline 返回值 函数名(参数)
{
}
四、C++中函数的参数能够有默认值
一、函数的默认参数要靠右。
二、默认参数要尽可能要少用,由于可能会引用重载错误。
三、默认参数是编译器在编译时帮助赋值的,因此只能由全局变量、静态变量、字面值对参数进行赋值。
1、名字空间
C语言中的名字空间的划分:全局、局部、块
C++认为:全局空间用起很是方便,但若是把太多的东西放在全局空间会形成命名冲突,因此C++引用了这样一种机制就是名字空间。
名字空间:把全局的命名空间进一步分割,能够建立出一个个独立的命名空间防止相互之间冲突。
1、定义名字空间:
namespace name
{
变量;
函数;
结构、类;
}
2、名字空间的合并
a、同名的名字空间会自动合并。
b、在同一个名字空间中只标识符必须是惟一的。
3、定义与声明分开
namespace n1
{
//在名字空间中声明函数
void func(void);
}
// 在名字空间外定义函数
void n1::func(void)
{
}
4、如何使用名字空间中的内容
a、域限定符(::),直接使用,名字空间::标识符,这样的好处是绝对不会冲突,但就是麻烦了些。
b、using namespace 名字空间; 功能是把名字空间中的标识符对以后的代码所有公开。
c、using 名字空间::标识符,表示此标识符对后面的代码公开。
5、名字空间的嵌套
名字空间能够嵌套,但使用时要逐层解析。
namespace n1
{
int num = 10;
namespace n2
{
int num = 20;
namespace n3
{
int num = 30;
}
}
}
n1::n2::n3::num == 30;
n1::n2::num == 20;
n1::num = 10;
using namespace n1::n2;
六、全局空间归属为匿名空间
在全局空间定义的标识符都属于这个匿名空间,匿名空间默认开放。
若是函数中有同名的标识符把匿名空间中的屏蔽了,可使用空的域限定符表示它。
注意:不一样命名空间中的同名函数不构成重载,同一做用域下的同名函数叫重载。
2、class
一、C++的class与struct同样,是一种复合数据类型。
二、里面能够有变量用来表达属性,函数用来表示行为。
三、在C++的class与struct,几乎没有任何区别。
四、struct中默认访问属因而public,class中默认的访问属性是private。
五、在C++默认使用class,以示与C语言中的class进行区分。
练习:定义一个Date类: year,month,day,在类里提供
一、年月日是否有效,返回bool类型
二、是不是闰年,返回bool类型
三、求nextday() ,返回下一天的日期
四、写一个nextday(int n)表示n表后的日期,注意n可正可负
一、日期转换整天数
二、由天数转换成日期
3、class的构造函数
一、在建立对象时自动调用的函数,在整个对象的生命周期中必定会被调用一次,且只能被调用一次。
二、在构造函数中负责对成员变量的初始化、分配资源、设置对象的初始状态。
三、构造函数能够有多个版本,这些不一样的版本之间会构造重载,建立对象时的方式不一样、给的参数不一样会调用相应的构造函数,若是调用的构造函数不存在可能会形成编译错误。
// 无参构造
Student stu <=> Student* stup = new Student;
Student stu(参数列表) <=> Student* stup = new Student(参数列表);
四、若是类中没有定义构造函数,编译器会自动生成一个无参构造。
一旦定义了其它版本的构造函数,无参构造就不会再生成了,所以为了防止无参方式建立对象出错,在定构造函数时,至少要实现两个。
五、无参构造未必无参,在C++中函数能够有默认参数,若是有参构造所有设置了默认参数,就会和无参数构造有冲突,它们两个只能有一个存在。
六、所谓的"编译器生成的某某函数"
"编译器生成的某某函数",不是真正意义上的函数,编译做为指令的生成者,只要生成具备某些函数功能的指令即,没有必须生成高级语言的主义上的函数。
七、何时调用无参构造
a、Student stu <=> Student* stup = new Student;
b、建立对象数组,每一个对象都会调用一次无参构造。
c、若是类A中有成员是类B,当执行守类A的构造函数前会自动调用类B的无参构造。
d、在类A中如何调用类B的有参构造
类A(参数列表):成员类B(参数列表)
{
...
}
八、类型转换构造函数
用一个数据给对象初始化,默认会自动调用构造函数,达到类型转换的效果。
这种方式虽然使用方便,但也会包容一些错误存在,若是想让代码检查更为严格可使用explicit关键字禁止隐式转换的方式调用构造函数。
九、也能够实现自动类型转换构造函数(默认)。
练习:
一、写一个Date类,有属性:年、月、日,实现其各类构造函数。
二、写一个Timer类(属性定义为私有,方法定义为公开)
有一个属性 unsigned int second;//second记录定时器的秒数
有一个属性 Action action;//定时器响应动做
typedef bool (*Action)(void *);
有一个方法setAction(Action a),当调用begin()方法以后,second秒以后自动调用a函数。
三、使用class方式实现五子棋。