数据结构
char|string
string a="a"; string b="b"; string c=a+b; //相加更简单
int len=c.size() //长度
getline(cin,str) //str为string类型
bool
非0为true,0为false;例如-5为true
指针
分配内存可以用malloc,c++中使用new分配内存,并返回该内存的地址;例如 int *p=new int; delete p;
动态数组分配 int *p=new int[10];释放内存 delete [] p; 动态分配内存
不能对未初始化的指针使用*来进行赋值
short类型的datas[3]数组的数组名相当于&datas[0],如果是&datas[0]是指向short类型的2字节内存块,而&datas则是指向整个数组的6字节内存块;数值相同,但是+1后跨度不同,一个跨度2字节,一个跨度6字节
命名空间
using namespace std; //将命名空间中的所有名称都可用
using std::cout; using std::cin; using std::endl;//只引入部分名词
数据溢出;如下图
函数
内联函数
原理是将函数调用这行代码用函数块取代掉,优化执行速度
申明 inline int f1(int); 实现 inline int f1(int x){.....} 即添加上inline标识符
引用
int a=3;
int &b=a; //b相当于a的别名;也可以用 int &b=*(&a)
引用必须在申明的时候初始化
引用放在函数参数中时也意味着函数参数名是调用该函数时传入的变量名的别名,两者指向的都是同一个内存块
int & func(int &a,int &b) //采取方式
可以用 func(const int &a,const int &b)来禁止修改a和b引用
默认函数
例如 int sum(int a,int b=1) //必须从右开始提供默认值
注意:只有原型上面提供默认值,实现上不要提供默认值
函数重载
函数模板
模板函数如下:
template <typename T> //申明和实现的时候都加上该语句
void Swap(T &a,T &b){ T c=a; a=b;b=c;}
int a=3;int b=4;double c=2.2;double d=3.3; Swap(a,b) Swap(c,d)
当使用int版本的时候,函数模板会生成int版本的函数;double的时候会生成double版本的函数;所以成为函数模板
非模板函数void Swap(Job &,Job &) > 具体化模板函数 > 模板函数 void Swap(T &,T &)
具体化模板函数如下:
template<> void Swap<Job>(Job &,Job &)
强制编译器实现某种类型的函数模板实现如下
template void Swap<short>(short &,short &);
类
1.基础
申明(头文件中)
class Stock{
private: //可以不用private修饰,因为默认访问控制即为private
long count;
long price;
long total;
void set_total(){total=count*price;} //可以不实现,放在cpp中实现
public:
long show() const; //const表示不修改隐式引用对象
void initIt(long count,long total)
Stock(const std::string company,long count=1,long price=100); //构造方法
~Stock() //析构函数,没有参数,必须这么写;对象过了生命周期后会调用该方法
实现
long Stock::show()const {....}
void Stock::initIt(long count,long total) {this->count=count;}
Stock::Stock(const std::string company,long count,long price){this->count=count;......}
Stock::~Stock(){}
定义和使用
include "stock.h"
Stock a; a.initIt(10,20); a.show();
几种方式创建对象 ;默认构造函数,当有其他构造函数的时候需要手动创建默认构造函数;默认构造函数要不没有参数,要不参数都有默认值
Stock a("company",10,10); //有参构造函数
Stock a; //无参构造函数
Stock a=Stock("company",22,33); (不推荐)
Stock a=Stock;(不推荐)
Stock *a=new Stock("company",11,12);
Stock *a=new Stock;
拷贝构造函数
值传递给函数
函数直接返回对象
值传递给对象
Line line1;
Line line2=line1; //值传递给了line2这个新对象
2.继承
class Child: public Base1,public Base2,public Base3{};
class Child:virtual public Base1{} //虚继承,通常用于接口
构造函数
Base1::Base1(int a,bool b)
Child::Child(int a,bool b,float c):Base1(a,b){....} //构造函数需要先初始化父类
Child::Child(int a,bool b,float c){...} //则将调用父类的默认构造函数
析构函数
先析构子类,再调用父类的析构函数
一般把析构函数申明为虚析构函数
因为如果是指针数组,类型为父类;当delete 每个元素的时候,如果不是虚析构函数,则会只调用父类的析构函数
细节
无法继承部分
基类的构造函数,拷贝构造函数,析构函数
基类的重载运算符
基类的友元函数
继承访问修饰符:基本使用public即可
Base1 & b1=child; //子类可以赋值给基类引用 b2.baseFunc()
Base1 *b2=&child; //子类地址可以赋值给基类指针 b2->baseFunc()
关于重写,重定义,重载
基类和子类属于不同的作用域
1.重写
必须是虚函数,且格式等保持一致;只需要在申明中使用virtual,父类和子类的申明都需要;实现中不需要
对象名.xxFunc()方法会调用对应的方法
如果不是虚函数(引用和指针会根据申明的类型调用该类型的方法)
Base1 &b1=child; b1.xxx()则会调用父类的方法
Base1 *b1=&child; b1.xxx()会调用父类的方法
如果是虚函数(引用和指针会根据指向的对象调用该对象的方法
因此上述会调用child的对应方法
纯虚函数 virtual void say()=0; //=0 意味着声明为纯虚函数
类中有纯虚函数时无法实例化(意味着是抽象类)
可以给纯虚函数提供实现
2.重定义
子类定义了父类的同名函数(非虚函数) 或者 定义了父类的同名函数(父类是虚函数)但是参数不同
如果要访问父类隐藏的函数,则使用Base::xxFunc()即可;包括可以使用父类的可访问成员变量 Base::_a
3.重载
在同一作用域下,函数同名,但是参数列表不一样
建议
基类应提供虚析构函数
应尽可能传递引用给函数,函数返回也尽可能返回引用;
直接返回引用意味着调用赋值拷贝方法和析构方法
除非要返回函数中临时创建的对象,那么需要返回对象而不是引用
尽可能使用const,例如 const Stock & Stock::getValue(const std::string v) const 来声明函数
尽可能使用私有数据成员,使用保护成员方法