目录
C++ 1 基础知识
C++ 对 C 的“增强”,表现在两个方面:
① 对C语言的扩充
② 增加了面向对象的机制
- C++ 中
main
函数必须为int
型 - 信息隐蔽是C++的一大特点
- 面向对象程序设计的4个主要特点:抽象、封装、继承、多态性
- 类是所有面向对象语言的共同特征
- 函数调用前必须声明
- 在引用变量前,对变量的定义可以出现在程序的任何行
- 函数的定义可以嵌套,但函数调用不能嵌套。c语言中“函数的定义不可以嵌套,但函数的调用可以嵌套
- C语言的关键字都是用小写字母书写的,不能用大写字母书写。C语言的关键字和标识符
注释
/*多行注释*/
//单行注释
头文件
#include<iostream>
using namespace std; //这两行都要
#include<string> //string 的头文件
#include<iomanip> //setw() setfill() 的头文件
类
- 类是对象的抽象,类是对象的模板,对象是类的特例,对象是类的具体表现形式
- 通过类实现封装性,接口与实现分离,信息隐蔽
- 公用成员函数是类的对外接口
class
声明的类,成员默认为private
struct
声明的类,成员默认为public
protected
不能被外界引用,但可以被派生的成员函数引用
class Student
//struct Student //为了兼容C
{
private:
int num;
public:
void data(){}
protected:
int a;
};
对象
- 对象定义
//1
class Student{
...
};
Student stu1,stu2;
//2
class Student{
...
}stu1,stu2;
//3(不常用)
class{
...
}stu1,stu2;
- 对象调用
//1
Student s;
s.num = 100;
s.data();
//2
Student s, *p; //指向对象的指针
p = &s;
p->num = 100;
p->data();
(*p).num =100; //或
(*p).data();
s.num = 100; //或
s.data();
//3
Student s;
Student &p = s; //取别名
p.num = 100;
p.data();
对象数组
Student stu[3]; //合法
Student stu[3] = {01, 02, 03}; //合法,若构造函数只有一个参数
Student stu[3] = {01, 02, 03}; //合法,但歧义,若构造函数不止一个参数,分别为构造函数传递一个参数
Student stu[3] = {01, 02, 03, 04}; //不合法
Student stu[3] = {Student(01, A),Student(02, B),Student(03, C)}; //合法
对象的赋值
- 对其中的数据成员赋值,不对成员函数赋值
- 类的数据成员中不能包括动态分配的数据
- 调用复制构造函数
Student stu1, stu2;
stu2 = stu1;
对象的复制
- 调用复制构造函数
Student stu2(stu1);
成员函数
- 类外定义成员函数,实现类的接口与类的实现细节分离,提高了软件工程的质量
- 类型转换函数只能作为成员函数,不能作为友元函数和普通函数
- 运算符重载必须作为成员函数:
=
->
下标运算符[]
函数调用运算符()
- 一般将单目运算符、复合运算符重载为成员函数
class Student{
private:
int num;
void fun(){} //工具函数,为本类函数所调用
public:
void fun1(){...} //类内定义
void fun2(); //类外定义的声明要在定义之前
};
void Student::fun2(){...} //类外定义
- 成员函数的目标代码存储在对象空间之外
int a;
cout<<sizeof(a); //=4
class Student{
private:
int a;
int b;
int c;
public:
void data(int x){...} //函数的目标代码存储在对象空间之外
};
cout<<sizeof(Student); //=12
输入输出 cin / cout
#include<iostream> //cin cout 的头文件
#include<iomanip> //setw() setfill() 的头文件
using namespace std;
cin>>x>>y; //输入时用空格间隔
cout<<"hello world!"<<endl; //endl即 “\n”
cout<<setw(6)<<a<<endl; //不足6位时 预留空位
cout<<setfill('0')<<setw(8)<<a<<endl; //不足8位时 补0
- 参考资料:[C++]如何输出数字时在前面加0
转义字符
\x
:16进制
\d
:十进制
\o
:八进制
字符串变量 string
string
不是基本类型,是 C++ 标准库中的一个字符串类- 字符串常量以
\0
作为结束符,字符串变量只存放字符串本身不包括\0
#include<string.h> //C语⾔的string头⽂件
char a[10]="11";
char b[3]="00";
char c=strcat(a,b) //1100
#include<string>
string a, c;
string b = "then";
b[2] = 'a'; //b = "than"
a = b; //相当于 strcpy(复制)
c = a + b; //相当于 strcat(连接)
if (a<b) ... //相当于 strcmp(比较)
srting d[3];
string f[3] = {"hello","world","!"};
int len=b.length();
int len=b.size();
数据类型的转换
标准数据类型的转换
- 在算术运算和关系运算中如果参与运算的操作数类型不一致,编译系统会自动对数据进行转换(即隐含转换),基本原则是将低类型数据转换为高类型数据。
低
char,short,int,unsigned,long,unsigned long,float,double
高
- 隐式类型转换
int i = 6;
i = 7.5 + i; //先自动将 6 转成 double 型
- 显式类型转换
int (89.5) //c++
(int) 89.5 //c
用户自定义类型的转换
- 转换构造函数
- 类型转换函数
运算符
- 逻辑运算符两侧运算对象可以是任何类型的数据
- 优先级:(从高到低)
()
[]
->
.
!
~
++
--
(type)*
取地址 &
sizeof
*
/
%
+
-
<<
>>
<
>
<=
>=
==
!=
位与 &
位异或 ^
位或 |
逻辑与 &&
逻辑或 ||
?:
=
+=
-=
*=
/=
%=
>>=
<<=
&=
^=
|=
,
- 参考资料:
作用域运算符 ::
#include<iostream>
using namespace std;
float a = 4.5;
int main(){
int a = 3;
cout<<a<<endl; //局部变量 a = 3
cout<<::a<<endl; //全局变量 a = 4.5
return 0;
}
长度运算符 sizeof
int a;
cout<<sizeof(a); // a 占用字节数 = 4
空间申请与释放运算符 new / delete
- 动态分配内存
new
/ 动态撤销内存delete
,new
建立的动态对象一般不需要对象名,通过指针访问,主要用于动态的数据结构,如链表
int *p1 = new int(456); //开辟一个存放整型的空间,该整数初值为456
int *p2 = new int[123]; //开辟一个存放整型数组的空间,不能指定初值
delete p1; //撤销用 new 开辟的空间
delete []p2; //撤销用 new 开辟的数组空间,指针名前只有一对方括号符号,不管所删除数组的维数。
//定义
Box *p3 = new Box; //开辟一个存放 Box 的对象的空间
Box *p4 = new Box(12, 13, 14);
//调用
cout<<p3->height;
//释放
delete p3;
自增运自减运算符 ++ / - -
c = a ++; //先运用再自增 c = a
c = ++ a; //先自增再运用 c = a + 1
c = a --; //先运用再自减 c = a
c = -- a; //先自减再运用 c = a - 1
- 参考资料:C++ 自增自减运算符 | 菜鸟教程
有默认参数的函数
- 函数定义在函数调用之前,函数定义中给出默认值
- 函数调用在函数定义之前,要在调用前有函数声明,在函数声明中给出默认值
- 一个函数不能即作为重载函数,又作为有默认参数的函数
//声明
float area(float r = 6.5);
float volume(float h, float r = 6.5);
void fun(int a, int b = 1, int c = 2); //有默认值的参数必须在最右
//引用
area(); //r = 6.5
area(7.5); //r = 7.5
volume(2.5); //h = 2.5, r = 6.5
volume(2.5, 7.5); //h = 2.5, r = 7.5
内置函数/内嵌函数/内联函数 inline
- 编译时,用函数体代替调用
- 调用一个函数的时间开销 << 小规模函数体中全部语句的执行时间
- 节省运行时间,却增加目标程序长度,适用于规模很小且使用频繁的函数
inline int max(int a, int b){
...
}
int main(){
int i = 2, j = 3, k;
k = max(i, j); //编译时,用函数体代替调用
return 0;
}
内置成员函数 inline
- 若类内定义的成员函数不包括循环等控制结构,C++ 会自动将其作为内置函数来处理
- 类外定义内置函数,必须将类的声明与成员函数的定义放在同一个头文件中,但不利于接口与类实现分离,不利于信息隐蔽,适用于规模很小且使用频繁的函数
class Student{
private:
int num;
public:
inline void fun3(){...} //类内定义内置函数
inline void fun4(); //类外定义内置函数的声明
};
inline void Student::fun4(){...} //类外定义内置函数
模板 template
函数模板
template <typename T> //用虚拟的类型T来表示
template <class T> //这两句都一样
T max(T x,T y){ //每定义一个函数模板前都要加上template这句话
...
}
template<typename T1,typename T2> //参数类型可以不止一个
类模板
- 类模板包含类型参数,又称为参数化的类,类模板是类的抽象,类是类模板的实例
//定义
template<class T>
class Compare{
public:
Compare(T a, T b){...}
T max(){...} //类内定义
T min(); //类内声明
private:
T x, y;
};
//类外声明
template<class T>
T Compare<T>::min(){...}
//调用
Compare <int> cmp(4, 7);
//参数类型可以不止一个
template<typename T1,typename T2>
异常处理 try throw catch
类声明、函数定义的分离
(1) 类声明头文件
//student.h
#include<iostream>
using namespace std;
class Student{
public:
void fun();
}
(2) 类成员函数的定义的文件
//student.cpp
#include<iostream>
#include "student.h"
using namespace std;
void Student::fun(){...}
(3) 主文件
//main.cpp
#include<iostream>
#include "student.h"
using namespace std;
int main(){
Student stu;
stu.fun();
return 0;
}
- 在实际工作中,将若干个常用功能相近的类声明集中到一起,形成类库
参考资料
- [1]谭浩强.C++面向对象程序设计(第2版)北京:清华大学出版社,2014.
C++ 1 基础知识
C++ 2 组合与继承
C++ 3 构造函数与析构函数
C++ 4 引用、指针、常量、静态、友元
C++ 5 多态性
C++ 6 输入输出流