指针
相关概念的理解容易混淆,记住之前学习理解的一个准则!*p 的理解意义就是p 所指向的那个东西
- 取地址符&
- 解引用运算符*
结构体
一些概念
- 结构体:构造(定义新的数据类型)
- 结构体变量:定义(两种);结构体变量访问结构体里面的成员:
.
;指针访问成员的时候->
- 结构体数组:变量很多
- 结构体指针:指向结构体变量的指针,定义:
struct Student *p
;指向结构体数组的指针
C 里面的结构体、共用体、枚举体根据这几类来构造新的数据类型,比如链表的初始实现,就是利用指针和结构体来实现
- typedef给结构体制定新的类型名 eg:计数专用变量
typedef int Count
C++相对 C
C 语言是一种混合型语言(20 世纪 80 年代兴起),它保留了 C 语言所有的优点,同时又增添了面向对象的编程机制,我们可以将 C 语言视为 C 语言的改进和扩展。
基于 C 语言开发的 C 语言兼容 C 语言,因此用 C 语言编写的程序基本上可以不做改动地用于 C。相对于 C 语言,C++语言对 C 语言的功能做了一定的扩充,同时增添了面向对象编程机制。引入面向对象编程机制,主要是为了提高开发效率。
早期 C 许多的工作是对于 C 的强化和净化,并把完全兼容 C 作为强制性要求。C89、C99 中许多的改进正是从 C 中所引进。可见,Stroustrup 对 C 语言的贡献非常之大。今天不管你对 C 怎么看,C 的确扩展和进化了 C,对 C 造成了深远的影响。
- 在 C 兼容 C 的过程中遇到了不少设计实现上的麻烦;以及守旧的 K&R C 程序员对 Stroustrup 的批评。很多人说 C 的恶梦恶梦就是要去兼容于 C,这并不无道理(Java 就干的比 C++彻底得多),但这并不是 Stroustrup 考虑的,Stroustrup 一边在使尽浑身解数来兼容 C,另一方面在拼命地优化 C。
- C 最大的竞争对手正是 C,他的目的就是——C 能做到的,C 也必须做到,而且要做的更好。大家觉得是不是做到了?有多少做到了,有多少还没有做到?
- 对于同时关注的运行效率和开发效率的程序员,Stroustrup 多次强调 C 的目标是——“在保证效率与 C 语言相当的情况下,加强程序的组织性;能保证同样功能的程序,C 更短小”,这正是浅封装的核心思想。而不是过渡设计的 OO。
- 《C 演化和设计》这本书中举了很多例子来回应那些批评 C 有运行性能问题的人。C 在其第二个版本中,引入了虚函数机制,这是 C 效率最大的瓶颈了,但我个人认为虚函数就是多了一次加法运算,但让我们的代码能有更好的组织,极大增加了程序的阅读和降底了维护成本。(注:Lippman 的《深入探索 C 对象模型》也说明了 C 不比 C 的程序在运行性能低。Bruce 的《Think in C++》也说 C++和 C 的性能相差只有 5%)
- 这本书中还讲了一些 C++的痛苦的取舍,印象最深的就是多重继承,提出,拿掉,再被提出,反复很多次,大家在得与失中不断地辩论和取舍。这个过程让我最大的收获是——a) 对于任何一种设计都有好有坏,都只能偏重一方,b) 完全否定式的批评是不好的心态,好的心态应该是建设性地批评。
相对运行于虚拟机语言,C/C 直接以静态形式把源程序编译为目标平台的机器码。一般而言,C/C 程序在编译及链接时可进行的优化最丰富,启动时的速度最快,运行时的额外内存开销最少。而 C/C 相对动态语言也减少了运行时的动态类型检测。此外,C/C 的运行行为是确定的,且不会有额外行为,也不会有如垃圾收集(GC)而造成的不确定性延迟,而且 C/C 的数据结构在内存中的布局也是确定的。有时 C 的一些功能会使程序性能优于 C,当中以内联和模版最为突出,这两项功能使 C 标准库的 sort()通常比 C 标准库的 qsort()快多倍(C 可用宏或人手编码去解决此问题)。另一方面,C/C 能直接映射机器码,之间没有另一层中间语言,因此可以做底层优化,例如使用内部(intrinsic)函数和嵌入汇编语言。然而,许多 C++的性能优点并非免费午餐,代价包括较长的编译链接时间和较易出错,因而增加开发时间和成本。
vector
C++模板知识
- 函数模板
- 类模板
STL 概述当中,vector 容器,顺序容器:向量 vector、列表 list、双端队列 deque
https://www.cnblogs.com/mr-wid/archive/2013/01/22/2871105.html
C 常用字符函数
Printf()
Scanf()
Putchar()
Getchar()
Puts(str)
Gets(str)
Strcat(str1,str2):连接字符串
复制函数:将 str2 复制给 str1
Strcpy(str1,str2)
在 C++里面会报错
解决 ①:将函数 strcpy 改成 strcpy_s,中间加一个参数——复制的长度
Strncpy(str1,str2,n):复制函数,将 str2 的前 n 个字符复制给 str1
Strlen(str):检测 str 的字符串长度
Fopen(文件名,使用文件方式)
fclose(文件指针)
改进
v I/O 流
scanf===cin>> >>endl;
Print===cout<< <<endl;
换行符:endl 和 “\n”
v 注释
/* */
//
v const 定义常量
之前 C 语言里面用的是宏定义#define Π 3.1415927,但是宏定义有时候太“死板”
类和对象
类的形式?
Class wuzutao
{
private:
public:
protect:
};
数据成员
成员函数:
类内实现=和普通函数的实现一样
类外实现=void Date::Display(){}
类定义对象?
① 花括号内定义
② 花括号外定义
访问对象?
访问的是类内的成员
① 圆点访问形式
② 指针访问形式
this 指针?
每个成员函数都会有一个特殊的隐含指针——this 指针。
调用形式:cout<<this<year<day<<endl;
构造函数和析构函数
构造函数的作用就是适当地给类进行初始化的作用
无参数的构造函数
带参数的构造函数
拷贝构造函数,这里不是太懂!
拷贝构造函数声明
拷贝构造函数定义和实现
析构函数
一般默认,如果自己写的话就是
析构函数的声明:
~类名();
析构函数的定义和实现:
类名::~类名(){……}
数据的共享和保护
数据共享 static
- 静态数据成员
声明:static 数据类型 静态数据成员名;
初始化在类结束和类中函数实现的中间
之后访问(通过类名/对象名来访问):
私有的静态成员只能通过间接的方式来访问===静态成员函数
对象名.公有静态成员变量名
对象名::公有静态成员变量名 - 静态成员函数
没有 this 指针
声明:static 返回值类型 静态成员函数名(形参表)
之后访问(通过类名/对象名来访问):
类名::静态成员函数名(实参表)
类名.静态成员函数名(实参表)
数据保护 const
- 常数据成员
有些时候,希望不用全局变量,因为这样不好移植,所以用到 const 场数据类型,相当于每次用不同场合用到这个类,都是这些用到这些固定的数据
一般结合 static 来避免数据赘余
eg:类 Circle 中
定义:const double PI;
初始化只能在构造函数后面的初始化列表中:Circle (double r=0):PI(3.1415926)- 常成员函数
只访问类中的数据而不修改类中的数据成员,最好用到常成员函数
eg:只访问类中的半径
声明:Double GetRadius()const;
实现:double Circle::GetRadius()const{……} - 常对象
所定义的常对象 p1 在之后就不会被改变了
形式:const Person p1(17,“wu”);
- 常成员函数
类和类之间的关系
类的组合
直观:B 类中有 A 类定义的对象
构造函数的顺序:
对象成员的构造函数
自身的构造函数
构造函数有参数的时候:
怎么个表现形式呢?
B 类中 B 的构造函数后面带有 A 类在 B 类中所定义的对象,这个对象的参数用做左边 B 类构造函数的参数、
类的依赖
赌徒和骰子,这就是一种依赖关系,如果用组合关系的话,就会影响到生命周期问题
Class 🎲{};
Class 🕵️♂️
{
public:
Void play(🎲1,🎲2,🎲3)
{……}
};
类的继承和派生
一、派生类的定义:
父类 class Base{}
派生子类:单一继承 class Derived:public Base{};
多重继承 Class Derived:public Base1,pretect Base2{};
继承的类型:
单一继承:只有一个基类
多重继承:有多个基类
继承方式:
private 继承:所有的数据成员都为子类的的私有成员
public 继承:父类的数据类型怎样,在子类类型不变
protect 继承:所有的数据成员和成员函数都为字类的保护成员
ps:① 父类的 private 数据成员和成员函数不能被子类所继承
② 一般很少用 protect 和 private 两种继承,因为两种改变了之前基类的访问属性,限制了这些的进一步派生,所以很少使用
二、派生类的构造和析构
构造和析构的调用顺序:
① 所有虚基类的构造函数
② 基类的构造函数
③ 对象成员的构造函数
④ 自身派生类的构造函数
ps:析构函数的调用顺序则正好相反、
虚基类保证调用一次构造函数。两个子类都有同一个基类的虚基类继承,构造函数只调用一次
带参数的构造函数:
子类里面,构造函数的初始化要连带着基类的构造函数的初始化
eg:classA(int a,int b,int c):classB(a*2),classC(a,b){}
三、同名冲突和解决方案
解决 ① 双冒号法::
基类和子类当中有相同名字的数据成员和成员函数,
访问的时候:相同的名字::数据成员/成员函数
解决 ② 定义虚基类 virtual
eg:class furniture{};
Class sofa :virtual public furniture{};
Class bed:virtual public furniture{};
Class sofabed:public sofa,public bed{};
四、赋值兼容规则