~1 库
写xx.h库时
#ifndef _xx_h
#define _xx_h
#endif _xx_h
//确定xx.h库一共只被调用一次,引用库相当于把库中的代码复制过来
~2 友元
class node{
private:
int G1,G2;
friend void work();//申明work函数是友元,可以调用node类里的私有变量
public:
node(int _G1=0,int _G2=0){G1=_G1,G2=_G2;}
}G;
int work(){
return G.G1+G.G2;
}
~3 运算符重载 (4种方法) (operator +)
method 1 (局部重载)
class node{
private:
int G1,G2;
public:
node(int _G1=0,int _G2=0){G1=_G1,G2=_G2;}
node operator +(const node b){return node(G1+b.G1,G2+b.G2);}
/*
node operator +(const node b)const {return node((*this).G1+b.G1,(*this).G2+b.G2);}
//直接在里面调用G1,G2,相当于(*this).G1,(*this).G2
*/
}G;
method 2 (局部重载)
class node{
private:
int G1,G2;
public:
node(int _G1=0,int _G2=0){G1=_G1,G2=_G2;}
node operator+(const node b);
}G;
node node::operator +(const node b){return node(G1+b.G1,G2+b.G2);}
//相当于先定义要重载运算符,再在下面重载
method 3 (全局重载)
class node{
private:
int G1,G2;
public:
node(int _G1=0,int _G2=0){G1=_G1,G2=_G2;}
friend node operator +(const node a,const node b);
}G;
node operator +(const node a,const node b){return node(a.G1+b.G1,a.G2+b.G2);}
//友元的作用是让重载时能调用到G1,G2,若是G1,G2在public中可以不用开友元
method 4 (全局重载)
class node{
private:
int G1,G2;
public:
node(int _G1=0,int _G2=0){G1=_G1,G2=_G2;}
friend node operator +(const node a,const node b){return node(a.G1+b.G1,a.G2+b.G2);}
}G;
//相当于把method3的重载和开友元合并到一起来写,算是重载运算符的特殊写法
/*
全局重载 vs 局部重载
即 重载全局函数 vs 重载成员函数
2+node(2,3)时,全局重载会默认先把2类型转化成node(2),可以过编译
而局部重载则过不了编译
*/
~4 重载运算符 += ++ >> << [] =
class node{
friend istream& operator >>(istream &in,node &G);//给它开友元
friend ostream& operator <<(ostream &out,const node &G);//给它开友元
//必须开全局变量
//可以合在一起写
private:
public:
int G1,G2;
int s[10],*p;
node(){G1=0,G2=0,p=new int;}
node(int _G1,int _G2){G1=_G1,G2=_G2,p=new int;}
~node(){delete p;}
node &operator +=(const node &b){
(*this)=node(G1+b.G1,G2+b.G2);
return *this;
}
// int下 a+=b <==> a=a+b <==> a加上b 并且 返回值为a
int &operator[](int x){return s[x];}//函数名前加& 可以左值调用,相当于return后面的参数
node &operator=(const node &x){
if(this==&x)return *this;//一定要判=左右是否相等,不然下面delete指针会使代码出错
delete p;
p=new int;
*p=*x.p;
G1=x.G1,G2=x.G2;
for(int i=0;i<10;i++)s[i]=x.s[i];
return *this;
}
node& operator++(){//重载 前缀++
G1++;
return *this;
}
node operator++(int x){//x为形式参数,无意义,表示重载 后缀++
node tmp;
tmp=*this;
//这里不能合写成node tmp=*this,因为这相当于直接构造tmp,用的是默认的赋值,写了node(node &G){}的构造函数才可以合写
G1++;
return tmp;
}
//函数名前加&,表示反回的是tmp的地址(左值)而不是右值
//前缀++A,前缀--A,+=,-=函数名前面都要加&
//后缀A++,后缀A--函数名前面不能加&
};
istream& operator >>(istream &in,node &G){//流读入
// cout<<"####"<<endl;
in>>G.G1>>G.G2;
return in;
}
ostream& operator <<(ostream &out,const node &G){//流输出
// cout<<G.G1<<" "<<G.G2<<endl;
out<<G.G1<<"/"<<G.G2;
return out;
}
//流输入时G前面不能加const,不然不能修改G了
//流输出时G前面加了const,则G传进来的可以是左值或右值,不然右值不能传进来,因为计算机可能认为G会被修改,但右值是不能被修改的
~5 类 函数写法
**
class node{
private:
int G1,G2;
public:
node(int _G1=0,int _G2=0){G1=_G1,G2=_G2;}
int calc(){
return G1+G2;
}
}G;
**
class node{
private:
int G1,G2;
public:
node(int _G1=0,int _G2=0){G1=_G1,G2=_G2;}
int calc();
}G;
int node::calc(){
return G1+G2;
}
//以上两种写法等价,一般大工程题采用第二种先申明后定义的方式,看着更清晰(即函数的先申明后定义)
~6 类 构造函数和析构函数
//构造函数为生成类时自动调用的,析构函数为函数消亡时自动调用的
class node{
private:
int G1,G2;
int *p;
public:
node(){G1=10,G2=2;}
node(int _G1){G1=_G1,G2=1000;}
node(int _G1,int _G2){G1=_G1,G2=_G2;}//以上三个都为构造函数,传入参数数量或类型不同
//or
node(int _G1,int _G2):G1(_G1),G2(_G2){}//先令G1=_G1,G2=_G2,在调用括号里的代码
//如果没有自定义构造函数,系统将自动生成一个默认构造函数 node(){} ,所有元素一开始都为随机值
//如果同时被匹配上多个同名函数/构造函数,则会报错
~node(){delete p;}//如果类中存在指针,在程序运行过程中可能有p=new int,所以要把内存释放,不然会内存泄漏
//如果没有自定义析构函数,系统将自动生成一个默认构造函数 ~node(){} ,表示什么也不做
}G;
~7 指针
int *p,*q;
int a=3,b[3];
p=&a;//取a的地址,p指向了a
q=b;//b其实记录的是数组b[3]的首地址,这里把b的地址赋值给了q,相当于可以用q调用b数组,q[i]与b[i]相同
int *p=new int;//动态申请内存
delete p;
int *q=new int[10]//申请了一个数组,q指向其首地址,可以把q[i]当成数组看
delete[] q;
//指针指向下一个地址或程序结束时,一定要把空间回收掉,不然会内存泄漏
int *p[10];//指针数组
for(int i=0;i<10;i++)p[i]=new int[10];
for(int i=0;i<10;i++)for(int j=0;j<10;j++)p[i][j]=1;
for(int i=0;i<10;i++)delete[] p[i];
//申请二维数组
int **q;//多级指针
q=new int*[10];
for(int i=0;i<10;i++)q[i]=new int[10];
for(int i=0;i<10;i++)delete[] q[i];
delete[] q;
//申请二维数组
int &j=i;//j可以引用i,即j成为了i的别名,调用j就相当于调用i
//定义引用类型的变量时必须立即对它初始化,不能写成 int &j;j=i
void F(int x,int y){
cout<<"!!!"<<x<<" "<<y<<endl;
}
int main(){
void (*p)(int,int);//函数指针 void表示函数返回类型,(int,int)表示传入参数类型
p=F;//表示p指向F函数的入口地址,即以下可用p代替F
p(2,3);
return 0;
}
const int *p=new int;//不能改*p的值
int *const p=new int;//不能改p指向的地址
~8 template模板
template<class T>
T Add(T a,T b){return a+b;}
template<typename T>//这里class和typename等价,但建议写typename以和类class区分
T Add(T a,T b){return a+b;}
template<typename T>
class node{
public:
int x,*p;
T G;
T Work(T x,T y){
return x+y;
}
};
int main(){
node<int> A;//一定要申明T的类型(此处为int)
node<int> *B=&A;
A.x=1;
B->x=1;//这两种用法等价,单纯的node类型用".",指针用"->"
// !!! B->x就是(*B).x
A.p=new int;
B->x=new int;//二者等价
*(A.p)=3;
*(B->x)=3;//二者等价,*放最外面
return 0;
}
~9 可变参数模板 ...
#include<bits/stdc++.h>
using namespace std;
void debugPrint(){cout<<endl;}//最后还要写一个传入变量数为0的函数
template<typename T,typename ...T2>
void debugPrint(T a,T2... b){//T2... b表示传入多个变量(变量数为>=0的任意个)
cout<<a<<" ";
debugPrint(b...);
}
int main(){
std::string str("test message");
debugPrint("Hello, Happy World!", 19260817, false, str);
debugPrint("debug");
return 0;
}
~10 main函数传参数
int main(int agrc,char *agrv[]){
cout<<agrc<<endl;
for(int i=0;i<agr;i++)cout<<agrv[i]<<" ";cout<<endl;
return 0;
}
//传参进去的变量名称并不是限制死为agrc和 *agrv[],也可以改成如以下的写法
int main(int num,char *nmdp[]){
cout<<num<<endl;
for(int i=0;i<agr;i++)cout<<nmdp[i]<<" ";cout<<endl;
return 0;
}
/*
命令行输入
./a 233 abc
程序输出
3
./a 233 abc
*/
~11 Lambda表达式 最简单应用
bool cmp(pp x,pp y){return x.fi+x.se<y.fi+y.se;}
int main(){
sort(a+1,a+n+1,cmp);
}
可改为
int main(){
sort(a+1,a+n+1,[](pp x,pp y)->bool{return x.fi+x.se<y.fi+y.se;});
}
//[]内先不考虑,()内表示传入参数,bool表示函数返回值,{}内为函数主体
//像sort一样很多系统自带函数支持Lambda表达式
int a[5],b=3;
auto func = [=](int x,int y)->int {return x+y+b+a[1];};
cout<<func(a[2],a[1])<<endl;
/*
//相当于把该Lambda表达式存到func里,func必须为auto类型
Lambda表达式可以捕获Lambda可见范围内的所有变量
[=] 表示捕获的变量为值传入
[&] 表示捕获的变量为地址传入
[&a] 表示捕获变量a用地址传入
[] 表示不能捕获变量
[=,&b,&c] 表示捕获变量b,c时地址传入,其他为捕获其他变量为值传入
[&,b,c] 表示捕获变量b,c时值传入,其他为捕获其他变量为地址传入
若为值传入,捕获的值为Lambda创建时捕获的值,而非使用时再次去捕获
*/
~12 && 右值引用
/*
值- 左值
\
右值- 纯右值
\
将亡值
*/
class node{
public:
int *p;
node(){}
node(node &&_G){p=_G.p;_G.p=nullptr;}
/*
&& 表示传入右值(这段代码下面传入的是将亡值)
右值自身不能被调用地址,即不能写成*this=G这种形式,所以主要一般是用在 直接把其内部指针的地址复制过来
//由于是将亡值,所以在复制地址完之后 应该在它消亡前把动态指针地址改成nullptr,防止其被delete掉
右值引用的目的主要是为了是减少内存拷贝,优化性能
*/
};
node Fun(){
node S;
S.p=new int[10];
for(int i=0;i<10;i++)S.p[i]=i;
return S;
}//此处返回的是将亡值
int main(){
node G(move(Fun()));//给G赋初值时传入的是一个右值(将亡值) move(x)表示将x强行转换成右值
for(int i=0;i<10;i++)cout<<G.p[i]<<" ";
cout<<endl;
return 0;
}
/*
输出结果为:
0 1 2 3 4 5 6 7 8 9
*/
~13 组合和继承
//组合--将point当成line的成员函数
class point{
int x,y;
};
class line{
point a,b; //point a,b被称为对象成员
};
//继承--将point的代码继承到point2中,继续新添加功能
class node{
private:
int a;
protected:
int b;
public:
int c;
}
class node2:public node{//public继承
};
//private:只能被当前类中的成员函数访问
//protested:只能被当前类和派生类中的成员函数访问
//public:可以被所有函数访问
//private继承:将基类的public类型变成private类型,基类的protected类型仍为private类型(相当于与private取min)
//protected继承:将基类的public类型变成protected类型后继承(相当于与protected取min)
//public继承:完全继承基类(相当于与public取min)
//ps:无论是哪种继承方法,基类中的private都不能被继承
//派生类调用构造函数时:先调用基类的构造函数,再调用对象成员(如果存在)的构造函数,最后调用自己的构造函数
//派生类调用析构函数时:先调用自己的析构函数,再调用对象成员(如果存在)的析构函数,最后调用基类的析构函数
class node{
public:
int a;
int b;
int c;
node(int _a=0,int _b=0,int _c=0):a(_a),b(_b),c(_c){cout<<"new node "<<a<<" "<<b<<" "<<c<<endl;}
~node(){cout<<"end node"<<endl;}
int F(){return a;}
node &operator=(const node &other){
if(this==&other)return *this;
a=other.a,b=other.b,c=other.c;
return *this;
}
};
class node__{
public:
int a;
node__(){cout<<"new node__"<<endl;}
~node__(){cout<<"end node__"<<endl;}
};
class node2:public node{
public:
int G;
node__ A;
node2():node(1,2,3){cout<<"new node2"<<endl;G=4;}//先调用node(1,2,3),再调用node__的构造函数,最后调用括号里的
or
node2(){cout<<"new node2"<<endl;G=4;}//等价于 node2():node(){cout<<"new node2"<<endl;G=4;} 调用node()默认构造函数
~node2(){cout<<"end node2"<<endl;}//先调用括号里的,再调用node__的析构函数,最后调用node的析构函数
int F(){return G;}//此函数F()与基类中F()名称与调用类型完全相同,此时认为是派生类里的新函数覆盖了基类里的旧函数
node2 &operator=(const node2 &other){
if(this==&other)return *this;
G=other.G,A=other.A;
node::operator=(other);
//调用基类的赋值函数,尽管other是个node2类型,但这样调用会把other的基类传进去(C++规定派生类函数能自动转化成基类函数)
return *this;
}
};
/*
调用node2 A; 输出如下
new node 1 2 3
new node__
new node2
end node2
end node__
end node
or
new node 0 0 0
new node__
new node2
end node2
end node__
end node
*/
~14 多态性、虚函数、纯虚函数、抽象类
//编译时的多态性
int f(){return 1;}
int f(int x){return 2;}
//编译时的多态性
int operator+(int a,int b){return a+b;}
int operator+(pp a,pp b){return pp(a.fi+b.fi,a.se+b.se);}
//运行时的多态性
class Shape{
public:
virtual double S(){return 233;}//前面加virtual,定义虚函数
virtual ~Shape(){}
/*析构函数前面务必加上virtual(一定要写带virtual的析构函数)
加上virtual后,一个基类的指针指向派生类,其消亡时本来只会调用基类的消亡函数
但基类的消亡函数前面如果带了virtual,它会先去调用派生类的消亡函数,再来调用基类的函数
*/
};
class Circle:public Shape{
public:
double r=1;
virtual double S(){return pi*r*r;}//此处前面virtual可以不加
};
class Rectangle:public Shape{
public:
double a=2,b=3;
virtual double S(){return a*b;}//此处前面virtual可以不加
};
int main(){
Circle A;
Rectangle B;
Shape *p=&A,*q=&B;
cout<<p->S()<<" "<<q->S()<<endl;
/*
本来p是一个Shape的指针,其指向派生类,只能调用派生类的基类的成员
但S()变为虚函数后,将先在派生类中找同名函数(名称和参数类型都相同),若存在则调用派生类中的函数,找不到则调用原函数
*/
Shape *t=new Circle;
delete t;
/*
由于Shape的析构函数前面带了virtual,此时先调用Circle的析构函数,再调用Shape的基类函数
Circle的析构函数会把new Circle开的Circle类中的a,b的空间释放掉
所以用类来写多态时,基类函数前面一定要带virtual
*/
return 0;
}
/*
输出为 : 3.14159 6
若将virtual去掉,输出为: 233 233
*/
virtual double S(){return 233;}//虚函数
virtual double S()=0;//纯虚函数
/*
将上面改成下面后上述代码也成立
区别:如果一个函数具有至少一个纯虚函数,则其被称为抽象类,抽象类可以创建指针(如Shape *p),但不能创建该类对象(如Shape C)
因为类中有纯虚函数,其为未定义完全的函数
*/
~15 文件输入输出
ofstream out("1.in");//另一个名为out的输出文件流和1.in相关联,此时会自动先清空1.in(若1.in不存在会新建一个)
out<<1<<" "<<2<<endl;//将1 2写入到out缓冲区,endl会自动将当前缓冲区的内容读入到1.in中
out.close();//关闭out和1.in文件的关联,并将out缓冲区剩下的内容全部读写入1.in
out.open("2.in")//可以令out再与2.in相关联
...
out.close();
ifstream in("1.in");//另一个名为in的输入文件流和1.in相关联(若1.in不存在不会新建)
int a,b;
in>>a>>b;//从1.in中读入
cout<<a<<" "<<b<<endl;
in.close(); //关闭out和1.in文件的关联
fstream io("1.in");//创建一个名为io的输入输出文件流,令其与1.in相关联
in.seekp(4);//找到1.in中第4个字节的位置,从这里开始读入或更改(0-base) ( 默认为从头开始,即in.seekp(0) )
int a,b;
in>>a>>b;//依次读入两个整数
in<<a<<b;//接着写入两个整数,直接将1.in中相应位置给替换掉,Ascii文件存储 233333算6个字符类型,而不是一个整数类型,占6个字节
io.close();
fstream io("1.in",fstream::in);//io相当于一个ifstream类型
fstream io("1.in",fstream::out);//io相当于一个ofstream类型
//判断文件是否读完:
while(in>>x){}
while((ch=in.get())!=EOF){}//读接下来一个字符放到ch中,ch为char
while(!in.eof()){in.read(ch,5);}//读入接下来5字节放到x中,ch为char*
ofstream out("1.in");
for(int i=1;i<=10;i++)out.write(reinterpret_cast<const char*>(&i),sizeof(int));//表示用1.in中数据用二进制文件存储(这里一个i占4字节)
out.close();
fstream in("1.in");
int x;
in.read(reinterpret_cast<char*>(&x),sizeof(int));//从二进制文件中读取数据
while(!in.eof()){
cout<<x<<" ";
in.read(reinterpret_cast<char*>(&x),sizeof(int));//从二进制文件中读取数据
}
in.close();
//采用二进制文件存储,可方便的用fstram类型定向修改某一位置的值
~16 函数指针
int calc(int a,int b){return a+b;}
int (*p1)(int,int); //返回类型(*指针变量)(形式参数表)
p1=calc;//让p1指向名为calc的函数
cout<<p1(3,4)<<endl;//等价于调用calc(3,4)
//or
cout<<(*p1)(3,4)<<endl;//等价于调用calc(3,4)
~17 模板的特定实例的友元
template<typename T1>class node;
template<typename T1>
class node2{
template<typename T1> friend class node;//所有node类模板都为友元
friend class node<T1>;//申明只有当node类 模板为int类型的特定实例 才为友元
};
~18 异常处理 try throw catch
class Error1{//定义一个异常类Error1
public:
void Output(){cout<<"error1"<<endl;}
};
class Error2{//定义一个异常类Error2
public:
void Output(){cout<<"error2"<<endl;}
};
class Error3{//定义一个异常类Error3
public:
void Output(){cout<<"error3"<<endl;}
};
void G(){
throw Error3();//异常抛出,此处零时用构造函数构造一个Error3类的对象,将它抛出
}
int main(){
try{
try{
cout<<"1"<<endl;
G();//此处已经throw,直接跳出当前try下面第一个捕获到它的catch,并调用当前已定义变量的析构函数
throw Error1();
throw Error2();
cout<<"2"<<endl;
}
//try后面要紧跟catch,中间不能有其他代码
catch(Error1 tmp){//此处未捕获到,继续跳出(若是不需要用到tmp,也可只定义要捕获的类型Error1)
tmp.Output();
}
}
catch(Error2 tmp){//未捕获到,继续向下
tmp.Output();
}
catch(...){//捕获剩余所有抛出的异常
cout<<"other Error"<<endl;
}
cout<<"3"<<endl;
return 0;
}
/*
输出:
1
other Error
3
*/
~19 静态成员与静态成员函数(例外:静态常量成员) static
class A{
private:
int x;
static int rate;//开了一个静态成员,为类A的所有对象共享
static const int GGG=20;//开了一个静态常量成员,每个对象单独开,必须在类定义时直接初始化
public:
A(int _x=0):x(_x){}
static void Set_rate(int x){rate=x;}//静态成员函数,用来访问静态成员(或其他静态成员函数)
int Get(){return x*rate;}
};
int A::rate=2;//为该静态成员申请空间,需要且仅需要申请一次
//静态常量成员是例外,不需要申请空间,其储存在类的对象中
int main(){
A a(2),b(3),c(4);
A::Set_rate(3);//调用类A中的静态成员函数,以修改静态成员rate
cout<<a.Get()<<endl;
cout<<b.Get()<<endl;
cout<<c.Get()<<endl;
return 0;
}
/*
输出:
6
9
12
*/
~more
/*
C++中,赋值是一种运算,返回值是左边对象
类是更合理的库
类没定义private还是public,默认是private
delete对象可以为空指针
不能delete一个地址两次
空指针p不能调用*p(若为node *p,p=nullptr,p不能调用node中的变量)
判断p!=nullptr常数极大(事实如此)
int Get(){return a.x;}
friend bool operator==(const Calendar& a,const Calendar& b){return a.Get() == b.Get();}
可能过不了编译,因为a,b前面加了const,而系统认为a.Get()可能会改变a,b的内部变量
所以应该再改成
int Get()const{return a.x;}//加上const
size_t 为unsigned int(32位机子)/unsigned long long(64位机子)
在类里面,函数可以直接调用在它下面写的函数,而不用在前面先定义
to_string(x) 将整数/浮点数类型的x转化成string
class A{
public:
class B{
};
};
B叫做嵌套类,和A没有任何关系(即B中元素不能调用A中private的元素),只是A可以调用它。如果class B定义在public中,相当于定义在外面
*/
~more more
/*
1.
0开头为8进制
0x开头为16进制
2.
cout<<"1as\023";读到\0为止
cin>>s;//char *s 读入最后会加入\0
3.
特定只能重载成成员函数不能重载成友元函数的4种操作符: =,(),[],->
特定只能重载成友元函数不能重载成成员函数的操作符: <<,>>
4.不能解引用空指针
5.
char s[10];
sizeof(s) =10 数组所占字节大小
char *s=new char[10];
sizeof(s) =4/8 指针所占字节大小(因为计算机不确定新开空间的具体大小)
strlen(s) 往后数到\0为止
6.
int const *p=new int;
const int *p=new int;
int *const p=new int;
前两种相同指针不能修改指向地址的值
第三种指针不能修改指向地址
7.
程序代码不能有二义性
尤其注意隐式转换
8.
cin.getline(s,10,'.');
cin.get(s,10,'.');
区别为get读到'.'结束后,'.'仍存在于输入流中
而getline读到'.'结束后,结束符'.'从输⼊流中被删除
9.
cout<<"\141"; 即输出a (97=64*1+8*4+1,8进制)
cout<<"\60"<<"\060"; 即输出两个0(48=8*6,8进制)
cout<<"\t"; 即输出tab
10.
int *p=new char[10] 动态开出的数组最后要手动加上\0
11.
class node{
int a,b;
public:
node(int _a=0,int _b=0):a(_a),b(_b){}
operator int() const{return a+b;}//类型转换,可用int(G)把G从node类型转化成int类型
};
12.
隐函数转换时不能存在二义性
class node{
int a,b;
public:
node(int _a,int _b):a(_a),b(_b){}//普通构造函数
node(const node &tmp){a=tmp.a,b=tmp.b;}//拷贝构造函数
node(int x=0){a=x,b=x;}//转换构造函数
node operator +(const node x)const{
node tmp(a+x.a,b+x.b);
return tmp;
}
operator int() const{return a+b;}//类型转换函数
};
int main(){
node G(3,4);
int x=2;
G+x;//这里有两种可行的隐函数转换,要么将G从node转成int,要么从将x从int转成node
//从而这里会编译报错
return 0;
}
13.
同时编译多个文件
g++ a.cpp b.cpp -o a
注意:a.cpp和b.cpp中只能有一个main函数
某一源文件中变量/函数/类前面加了static,则该变量/函数/类只能在该源文件中使用
不然,可以通过在另一源文件中加形如extern int a;/extern void init(); 的代码使得另一源文件也可以调用该变量/函数
不过extern的变量只能在其他源文件中一共定义一次(不算static)
ps:申明函数和类前面可以不加extern,加/不加是等价的
使用#include某一个库,相当于手动把源文件链接起来(显然不能相互引用形成环),最后形成森林一样的结构
14.
内联函数不能递归
15.
尾置返回
void init(){}
可以写成
auto init()->void{}
//使用尾置返回时前面要带个auto
lambda表达式要使用尾置返回
16.
class node{
public:
void calc(const node a)const{//前一个const表示该函数不能修改a,后一个const表示cosnnt不能修改*this
}
}
17.
void calc(const int &x){}
calc(3);//可以这样调用,可以当作给3这个常量开了个静态存储区,调用时虽然取地址了,但前面有个const,保证了其不会被修改
18.
class node{
static const int x=2;//直接在类里面赋初值
static int y;
const int z;//可以选择不直接赋初值,而是在构造函数的初始化列表中赋初值
node():z(3){}
};
int node::y=2;//要在外面定义+赋初值
19.
explicit:构造函数不能使用必须为显示转换,不能为隐式转换
class node{
private:
int a;
public:
explicit node(int _a=0):a(_a){}
};
int main(){
node A;
A=2;//编译报错,因为这里用到了int到node的隐式转换,但上面定义时写了explicit,要求必须为显示转换
A=node(2);//正确
return 0;
}
20.
int a=22;//10进制
int a=0x22;//0x开头为16进制
int a=022;//0开头为8进制
21.
char s[]="abb";//相当于开了个s[4],s="abb\0"
22.
char中'\0'的Ascii码为0
23.
strcpy(a,b) 拷贝到\0为止,\0也会被拷贝过去
24.
void solve(base x){//此处调用拷贝构造函数,而不是赋值"=" (若没有定义拷贝构造函数,系统会产生一个默认的拷贝构造函数)
return;
}
int main(){
base x;
solve(x);
return 0;
}
25.
cout<<setw(8)<<setfill('#')<<endl;//setw下一次有效,setfill永久有效
*/