C 语言是面向过程的程序设计, 强调程序的执行顺序, 自上而下, 而 C++ 是面向对象的程序设计, 将程序看做多个对象组成, 每个对象有自己的属性 (变量) 和行为(函数).
2. 属性是描述对象特征的数据, 行为是对象能进行的操作, 如英雄联盟里每一个英雄都有自己的属性 (生命值, 法力值, 防御力, 攻击力) 和行为(普通攻击, 施放技能 QWER).
C++ 编程规范:
类名第一个单词大写, 数据成员和变量小写;
成员函数第二个单词首字母大写;
成员函数类外定义, 类内声明;
Set 和构造函数的参数与数据同名, 用 this 访问;
一, 什么是类和对象
1. 类 (具有共性的实体) 其实是 C 语言结构体的升级版, 对象在程序中可以理解为编译器为之分配了存储空间的变量.
假如定义了一个带函数的结构体, 然后把 struct 改成 class
- class Stu
- {
- int id;
- char *name;
- void study()
- {
- cout<<name<<"正在学习 C++"<<endl;
- }
- };
在这里 class Stu 就是类, 用这个类定义一个变量 Stu czy; czy 就是对象
可以对对象进行操作如 czy.id =1;czy.study();
在 C++ 中后缀为 *.cpp, 编译器用 g++, 包含头文件 #include<iostream>
输入输出用 cin,cout, 需使用命名空间 using namespace std;
2. 命名空间用于解决命名重复问题, 自定义作用域将多个变量和函数封装起来, 如:
- namespace myName
- {
- int num = 10;
- void fun()
- {
- std::cout<<"in mynamespace fun\n";
- }
- }
然后在 main 函数中引用, myName::fun();
3.I/O 流 cin>> 和 cout<<, 就是 C 语言中的 printf()和 scanf()但是不用指定格式, cin 输入数据类型不匹配时不读取, 多个输入之间以空格分隔, 遇到空格时结束, 不检查数据长度, 有缓冲区溢出的危险. 所以有了 cin.getline(str, sizeof(str)), 类似于 c 语言的 fgets();
4.C++ 中结构名可以直接作为类型名(自动 typedef), 与 C 语言不同, c++ 中 const 修饰的值为常量, 存在文字常量区.
5. 缺省函数
带有缺省参数的函数, 如 void fun(int num = 0);
6. 重载函数
允许有同名的函数出现, 但是参数不同, 返回值不能作为区分的标志, 不能与缺省函数同名.
7. 类型转换
- char a = char(num);
- char *p = char *(num);
8.new/delete 运算符
还记得 C 语言中的 malloc 和 free 吧, C 语言中 free 释放后, 指针和空间都还在, 但是指针已经没有了对空间的操作权(好像还能读取), 所以应该使其指向 NULL
new 和 delete 不是函数是运算符
int num = 10;// 栈区定义一个变量
如 int *p = new int(100);// 在堆区开辟了一块 4 个字节的空间, 里面存了一个 int 型的数 100
而 char *str = new char[100];// 在堆区开辟了一块 100 个字节的空间, 首地址赋给 str
注意 new int(100) 和 new char[100]的区别(坑).
new 申请的空间自动赋值为 0
删除单个变量空间 delete num;, 删除数组空间 delete []str;
9. 引用
操作符 &, 代替指针, 给变量取个别名, 引用不占空间
- int num = 10;
- int &a = num;// 定义一个 num 的别名 a
引用必须赋初值, 定义后不能修改.
可作为参数和返回值, 提高程序的执行效率.
10.C++ 有封装性, 增加了对成员的访问权限
private 只能在类中访问, public 类中类外都能访问, class 类的成员默认为 private
还是那个类
- class Stu
- {
- private:// 这一行开始之后的所有成员都是私有成员
- int id;
- char *name;
- public:// 这一行开始之后的所有成员都是公有成员
- void study()
- {
- cout<<name<<"正在学习 C++"<<endl;
- }
- };
规范 1:C++ 中一般将属性设置为 private, 操作设置为 public, 然后每一个属性都有相应的操作, 如 setId(),getId(), setName(), getName()好像面向对象编程都是这个套路
规范 2: 成员函数一般放在类外定义, 类内声明, 定义时加 类名:: 指定
如 void Stu::setId(int num)
11. 构造函数
特殊的成员函数, 用于在定义对象时进行初始化
构造函数名称和类相同, 可以有参也可以无参, 没有返回值(包括 void), 由编译器自动调用.
如果没有自定义构造函数则使用默认的构造函数(空函数), 构造函数可重载, 可缺省.
使用 new 定义对象时也会调用构造函数 Stu *s2 = new Stu();
12. 析构函数
构造函数的反操作, 在删除对象或对象退出生命周期时完成反初始化操作, 如清理内存
在构造函数前加~ 号, 一般情况下析构函数由编译器执行, 使用 delete 时会触发调用
一般情况下不需要定义析构函数(没有为类中的成员开辟堆区内存)
如在构造函数中有
- Stu()
- {
- name = new char[100];
- }
则必须用析构函数
- ~Stu()
- {
- if(NULL != name)
- {
- delete []name;
- name = NULL;
- }
- }
每个类只有一个析构函数, 不能重载也不能有参数
13. 拷贝构造函数
特殊的构造函数, 定义对象时使用已存在对象完成初始化
名称与类相同, 无返回值, 参数必须是当前类的对象的引用
使用条件: 写 Stu s2 = s1; 和 Stu s3(s1); 时会调用拷贝构造函数, 而写 Stu s2 ; s2 = s1; 则不会调用拷贝构造函数.
一般情况下不需要自定义拷贝构造函数(和析构函数一样没有为类中的成员开辟堆区内存), 因为如果不定义拷贝函数编译器只会进行浅拷贝操作(只拷贝值, 不拷贝内存空间), 释放时会出现段错误
所以当类中有指针且为指针分配了空间时, 要自定义拷贝构造函数进行深拷贝.
- Stu(const Stu &s1)
- {
- id = s1.id;
- name = new char[strlen(s1.name)+1];
- strcpy(name, s1.name);
- }
类中有动态内存分配时, 需要自定义拷贝构造函数, 否则会因为多次释放同一段内存导致段错误(double free or corruption)
14.const 修饰的成员函数
- void setId(int num)const
- {
- }
称为只读成员函数, 只能读取成员值, 不能修改(除非是 mutable int id)
15. 对象数组: 有限个相同类型的对象构成的集合
Stu array[3]={Stu(1), Stu(2)};
16.this 指针
一个隐藏的指针变量, 是成员函数的第一个参数, 类型为对象的类型
如果对象的成员函数形参和属性相同, 可用 this 指定
用于规范:
- void setId(int id)
- {
- this->id = id;
- }
如果要重复调用成员如: s1.setId(10).getId(); 可使 setId()返回对象的引用(return *this)
17. 枚举(常与 switch 使用)
构造函数列表
- Stu():id(10), score(99.5)
- {
- }
使用方法和构造函数相同, 但是可以完成特殊成员的初始化如 const 修饰的成员
18.const 修饰的成员
只能用构造函数列表初始化, const 修饰的成员在不同的对象中可以有不同的值
19. 静态成员 static int num; static int getNum();
静态数据成员和静态成员函数, 初始为 0
静态数据成员在类外定义, 类内声明, 和类的其它成员不在一块内存, 不占用对象的空间, sizeof()不会计算.
属于整个类而不是某个对象, 可通过类名:: 对象访问 Stu::num
作用之一: 代替全局变量
静态成员函数不能使用非静态数据成员, 只能访问静态数据成员和全局变量, 不能使用 this
为了更好地操作使用静态数据成员而出现静态成员函数, 在定义对象之前即可操作静态数据成员.
20. 对象成员
即类的嵌套, 类似结构体嵌套, 一个类的对象作为另一个类的成员
给对象成员中的数据成员赋值要用构造函数列表
- class A
- {
- public:
- int aNum;
- A(){
- aNum = 1;
- cout<<"在 A 构造函数中"<<endl;
- }
- A(int num){
- aNum = num;
- }
- };
- class B
- {
- public:
- int bNum;
- A a;
- B()
- {
- bNum = 2;
- cout<<"在 B 构造函数中"<<endl;
- }
- B(int num):a(10)
- {
- bNum = num;
- }
- };
21. 友元
在类外访问类的私有成员
友元函数, 友元成员, 友元类
关键字 friend
友元函数: 将一个类外函数声明为 friend, 可以访问类的私有成员, 友元函数定义有顺序要求
友元成员: 一个类的成员函数声明为 friend 如: friend void Tch::getNum(), 另一个类的成员函数可以访问该类成员.
友元类: friend class Tch;
友元一般不使用, 因为破坏了函数的封装性
22. 运算符重载
也叫运算符重载函数, 为适应对象操作
- int operator +(A a1, A a2)
- {
- return a1.num+a2.num;
- }
运算符重载实质为函数重载, 必须遵循其原则
除了成员运算符 ".", "sizeof", 条件运算符 "?:", 作用域运算符 "::" 之外都可以重载, 重载后优先级和结合性不变
一般重载为友元函数或成员函数
单目运算符重载为成员函数, 双目运算符重载为友元函数
"=", "()", "[]", "->" 不能重载为友元
来源: http://www.bubuko.com/infodetail-2561444.html