文章目录
-
-
- 一、第一个C++程序
- 二、名字空间(命名空间) 改变作用域
- 三、C++的结构体,联合体,枚举
- 四、C++的字符串
- 五、C++的布尔类型: bool
- 六、操作符别名 //了解
- 七、C++的函数
- 八、C++的动态内存管理(什么是内存泄露,有什么危害)
- 九、C++的引用(Reference) (重点)
- 十、类型转换
- 十一、类和对象 //了解
- 十二、类的定义和实例化
- 十三 构造函数和初始化列表
- 十四 this指针和常成员函数
- 十五 析构函数(Destructor)
- 十六 拷贝构造和拷贝赋值
- 十七 静态成员(static)
- 十八 成员指针 //了解
- 十九 操作符重载
- 二十 继承(Inheritance)
- 二十一 多态(Polymorphic)
- 二十二 运行时类型信息 //了解
- 二十三 C++异常机制
- 二十四 I/O流 //了解
-
一、第一个C++程序
1 编译方式
1)gcc xx.cpp -lstdc++
tarena@ubuntu:~/me/C++/day01$ gcc first01.cpp -lstdc++
@ubuntu:~/me/C++/day01$ a.out
hello world!
2)g++ xx.cpp //推荐
tarena@ubuntu:~/me/C++/day01$ g++ first01.cpp
tarena@ubuntu:~/me/C++/day01$ a.out
hello world!
2 文件扩展名
1) .cpp //推荐
2) .cxx
3) .cc
4) .C
3 头文件
#include<iostream>
--> C++中和I/O相关的类型,对象,函数都在该头文件中
--> C++中绝大多数头文件没有.h后缀
--> C++开发中,可以直接使用c语言头文件中,同时还提供了一套不带.h的替换版本
eg:
#include <stdio.h> ==> #include<cstdio>
#include <stdlib.h> ==> #include<cstdlib>
#include <string.h> ==> #include<cstring>
4 标准的输入输出
1) 使用cin对象表示标准输入//类似scanf()
int i;
scanf("%d",&i);//C
cin >> i; //C++
-------------------------------------------------------
int i,double d;
scanf("%d%lf",&i,&d);//c
cin >> i >> d;//c++
注:">>"输入操作符
2) 用cout对象表示标准输出//类似printf()
int i=123;
printf("%d\n",i);//C
count << i << endl;//C++
注:"<<"输出操作符
--------------------------------------
int i = 123,double d = 4.56;
printf("%d,%lf\n",i,d);//C
cout << i <<','<< d << endl;//C++
二、名字空间(命名空间) 改变作用域
1 功能:
1) 避免名字冲突
2) 划分逻辑单元
2 定义名字空间
namespace 空间名{
名字空间成员1;
名字空间成员2;
...............
}
注:名字空间成员可以是全局函数,全局变量,自定义类型,名字空间.
3 名字空间成员使用
1)通过作用域限定操作符"::"
空间名::要访问成员;
eg:
"std::cout" 表示使用标准名字空间里面cout
2)名字空间指令
using namespace 空间名;
在该条指令以后的代码中,指定名字空间成员都可以见,可以直接访问,省略"空间名::"
3)名字空间声明
using 空间名::名字空间成员;
将名字空间中特定一个成员引入到声明所在的作用域中,在该作用域访问这个成员就如同是访问自己的成员一样,可以直接访问,省略"空间::"
4 全局作用域和无名(匿名)名字空间 //了解
1) 没有放在任何名字空间的成员,属于全局作用域,可以直接访问,如果和局部作用域的成员名字一样,局部优先;这时如果还希望访问到全局作用域的成员
可以通过"::成员"形式来显式指明
2) 定义名字空间时,可以没有名字,即为无名名字空间,对于无名空间里面的成员和全局作用域的成员一样,也可以直接访问,只是被局限在当前文件中
全局可在整个程序内使用
匿名名字空间只可以在本文件中使用
::变量名或函数名,是访问全局变量和全局函数的方法.
5 名字空间嵌套//了解
eg:
namespace ns1{
int num = 10;
namespace ns2{
int num = 20;
namespace ns3{
int num = 30;
}
}
}
cout << ns1::num << endl;
cout << ns1::ns2::num << endl;
cout << ns1::ns2::ns3::num << endl;
三、C++的结构体,联合体,枚举
1 结构体
1)当定义结构体变量时可以省略struct关键字
2)在结构体内部可以直接定义函数,称为成员函数(方法),成员函数中可以直接访问当前结构体中的其它成员
2 联合体(union)//了解
1)当定义联合体变量时可以省略union关键字
2)支持匿名联合
3 枚举
1)当定义枚举变量时,可以省略枚举关键字.
2)C++中枚举被看做是独立的数据类型,而c语言中枚举本质就是整型数.
enum STATE{SLEEP,RUN,STOP};
STATE s;
s = STOP;//C:ok,C++:ok
s = 2;//C:ok,C++:error
枚举可以当做返回类型.
四、C++的字符串
1 回顾c中字符串
1) 字面值常量 "hello"
2) 字符指针 char*
3) 字符数组 char[]
eg:
char* p1 = "abcdef";
char* p2 = "123456";
strcpy(p1,p2);//段错误
段错误信号 11
---------------------------
char arr1[] = "hello";
char arr2[] = "wangjianli";
strcpy(arr1,arr2);//内存越界,结果未知,危险!
--------------------------------
char arr[] = "hello";
char *p="world";
p = arr;//OK
arr = p;//error
---------------------------------------
2 C++可以完全兼容c中字符串表示方式,同时增加了string类型转换表示字符串.
- 1)字符串的定义
string s;//定义空字符串
string s = "xxxx"; //定义同时初始化
----------------------------------------------------
//下面两种写法实际初始化和上面相同
string s("xx");
string s = string("xx");
//char*类型指针,指向了一块在堆区动态分配的内存,这块内存存放了字符串的值.
namespace std{
struct string{
char *;
}
}
- 1) 字符串拷贝: =
string s1 = "hello";
string s2;
s2 = s1;//拷贝
- 2) 字符串的连接: + +=
string s1 ="abc";
string s2 = s1 + "def";
cout << s2 <<endl;//"abcdef"
- 3) 字符串比较: == != > < >= <=
if(s1 == s2){.....}
- 4) 随机访问: []
string s ="hello";
s[0] = 'H';
- 5) 成员函数
size()/length();//获取字符串长度
string str = "xxx";
str.size();
str.length();
c_str();//获取c风格的字符串(const char *)
string s1 ="xxx";
const char* s2 = "xxx";
s1 = s2;//OK
s2 = s1.c_str();//ok
void cfunc(const char* str){}
cfunc(str);
五、C++的布尔类型: bool
1 bool类型是C++中基本数据类型,专门表示逻辑值,逻辑值真为true,逻辑假为false
2 bool类型在内存占一个字节:1表示true,0表示false
3 bool类型变量可以接收任何类型表达式的结果,数值非零则为真,为零则为假.
六、操作符别名 //了解
&& <==> and
|| <==> or
^ <==> xor
{ <==> <%
} <==> %>
...
七、C++的函数
1 函数重载(overload)
1)定义
在相同作用域中,可定义同名函数,但是它们的形参必须有所区分(参数个数,参数类型,和形参变量名无关),这样的函数关系称为函数重载.
注:函数重载和返回类型无关
eg:图形库中绘图函数
void drawRect(int x,int y,int w,int h){....}
void drawCircle(int x,int y,int r){....}
......
--------------------------------------------------------
void draw(int x,int y,int w,int h){...}
void draw(int x,int y,int r){...}
......
2)函数重载匹配
调用函数时,编译器根据实参和形参匹配程度,自动选择最好的重载版本.
当前g++编译器匹配的优先级:(优先级以编译器的结果为准)
完全匹配>=常量转换>升级转换>降级转换>省略号匹配
char* > const char *
char = const char
- 当通过函数指针调用重载关系的函数时,根据指针类型选择匹配的重载版本.(函数指针在定义时已经匹配完成,函数指针是什么类型,调用什么类型的函数)
3)函数重载的原理 (函数的重入是什么????)
nm x.0
g++ 在编译函数,会进行函数换名
void func(int i,double j){}
_Z4funcid 4是函数名字符数 i 形参类型int d 形参类型double
C++的编译器是通过函数换名,将参数表的类型信息整合到新的函数名中,实现解决函数重载和名字冲突的矛盾.
(笔试题):C++中extern "C"声明作用?
可以在函数声明前面加入 extern "C" ,要求C++编译器不要对该函数进行换名,便于C程序直接调用.
注:被extern "C"声明的函数无法被重载.
--------------------------------------------
vi -O 用竖屏方式打开多个文件
vi -o 用横屏方式打开
vs
sp
Ctrl + W + W 进行换屏
2 函数的哑元参数 (C语言直接报错)
1)定义
定义函数时,只有类型而没有变量名形参被称为哑元.
void func(int /*哑元*/) {...}
2)使用哑元的场景
-->操作符重载,通过哑元区分前后++/--(后面讲)
-->兼容旧代码
eg:
//算法库:
void math_func(int a,int b){...}
//使用者:
int main(void){
math_func(10,20);
...
math_func(30,40);
}
--------------------------------------------
//算法库升级
//哑元作为一个显示标记,告诉程序员这个参数没用
void math_func(int a,int /*哑元*/){...}
//使用者:
int main(void){
math_func(10,20);
...
math_func(30,40);
}
3 函数的缺省参数(默认实参)
1) 可以为函数的参数指定缺省值,调用该函数时,如果不给实参,就会取缺省值作为默认实参.
void func(int a,int b=0/*缺省参数*/){...}
2) 靠右原则
如果函数的某个参数有缺省值,那么该参数右侧的所有参数都必须带有缺省值.
3) 如果函数声明和定义分开写,缺省参数应该写在函数声明部分,而定义部分不写(加注释标明);
void func(...);//函数声明
void func(...){...}//函数定义
- 4) 不要和函数重载形成歧义
void func(int a,int b=20,int c=30);
void func(int a);
func(10);
4 内联函数(inline) (笔试题)
1) 使用inline关键字修饰的函数即为内联函数,编译器将会 尝试 进行内联优化,可以避免函数的调用开销,提高代码的执行效率.
开销:保护现场,恢复现场......增加执行时间.
inline void func(void) {...}
内联关键字对程序的实现没有影响,影响的是编译器的执行.
内联是在编译时直接用函数机器指令替换调用语句的机器指令,避免调用的跳出跳入的时间耗费.(以空间换时间)
2) 使用说明
--> 多次调用的小而简单的函数适合内联函数
--> 调用次数极少或大而复杂的函数不适合内联
--> 递归函数不能内联(递归函数是否结束依赖于上一次的执行结果,执行次数不确定)
--> 虚函数不能内联(后面讲)
注: 内联优化只是一种建议,而不是强制要求,对于一个函数能否内联优化主要取决于编译器,有些函数不加inline修饰也会默认处理为内联优化;
有些函数即便加了inline修饰也会被编译器忽略掉.
八、C++的动态内存管理(什么是内存泄露,有什么危害)
1 回顾C语言中的动态内存管理
1)分配:
malloc()(calloc/realloc/brk/sbrk/mmap)
- 2)释放:
free()
2 C++的动态内存管理
1) 分配:
new,new[]
- 2) 释放:
delete,delete[]
内存分配时可以同时初始化 new int(200) 将存储区的值初始化为200
new[]分配,必须用delete[]释放,否则会发生内存泄露.
-std=c++11 使用C++11语法
笔试题(new,delete和malloc,free的区别)