C++程序可以不必严格按行书写,凡是可以出现空格的地方,都可以出现换行
临时变量不能作为非const引用
class P
{
public:
P(P &b); //形参非const引用
P operator+(const P&b)const
{return P();}
};
int main()
{
P x,y;
P z=x+y; //x+y得一个临时对象
//且将使用该对象作为实参调用复制构造函数为z初始化
//但临时变量不能作为非const的引用参数,所以将报错
//可将复制构造函数的形参改为 const引用,即P(const P &b);
函数返回值为引用类型
返回函数中定义的局部变量的引用,将导致无效,因为局部变量在函数结束时就已消失(生存周期结束),所以其引用为无效引用
int& fun()
{
int a=10;
return a;
}
int main()
{
cout<<fun(); //引发错误
}
枚举类型
enum Weekday{SUN,MON,TUE,WED,THU,FRI,SAT};//具有默认值0,1,2,···
enum Weekday{MON=1,TUE,WED,THU,FRI,SAT,SUN};//则值为1,2,3,···
- 枚举元素按常量处理,不能对它们赋值。
- 枚举型数据可以隐含转换为整型数据
- 整型数据到枚举数据的转换需要采用显式转换方式
enum GameResult{WIN,LOSE,TIE,CANCEL};
int main()
{
GameResult result;
enum GameResult omit=CANCEL; //enum可省,如上
for(int count=WIN;count<=CANCEL;count++) //隐含类型转换
{
result=GameResult(count); //显式类型转换
//result=static_cast<GameResult>(count); 亦可
if(result==omit)
cout<<"The game was cancelled"<<endl;
else
{
cout<<"The game was played ";
if(result==WIN)
cout<<"and we won!";
if(result==WIN)
cout<<"and we lost.";
cout<<endl;
}
}
函数重载
重载函数的形参必须不同:个数不同或者类型不同。 编译器不以返回值来区分函数
类的定义中,不同访问属性的成员可以按任意顺序出现,修饰访问属性的关键字也可以多次出现
对象所占内存空间只是用于存放数据成员,函数成员不在每一个对象中存储副本,每个函数的代码在内存中占据一分空间
联合体(好东西)
联合体的全部数据成员共享同一组内存单元,所以联合体变量中的成员同时至多只有一个是有意义的。另有以下限制:
- 联合体的各个对象成员,不能有自定义的构造函数、自定义的析构函数和重载的复制赋值运算符,不仅联合体的对象成员不能有这些函数,这些对象成员的对象成员也不能有,以此类推
- 联合体不能继承,因而也不支持包含多态
联合体也可以不声明名称,称为无名联合体。
各个对象的属性值可以各不相同,这样的属性称实例属性
不属于任何一个具体对象,类属性
在对类的静态私有数据成员初始化的同时,还可以引用类的其他私有成员。例如,如果一个类T存在类型为T的静态私有对象,那么可以引用该类的私有构造函数
常引用
对于在函数中无需改变其值的参数,不宜使用普通引用方式传递,因为那会使得常对象无法被传入,采用传值方式或传递常引用的方式可避免这一问题。对于大对象来说,传值耗时较多,因此传递常引用为宜。复制构造函数的参数一般也宜采用常引用
指针
赋给指针变量的值必须是地址常量(如数组名)或地址变量,不能是非0的整数,但可以赋值0,表示空指针
可以声明void类型的指针,使用类型显式转换,通过void类型指针即可访问任何类型的数据,void类型指针一般只在所指数据类型不定时使用
typedef int (*DoubleIntFunction)(double);
这声明了DoubleIntFunction为“有一个double形参、返回类型为int的函数的指针”类型的别名。然后可直接用DoubleIntFunction funcPtr;
this指针是一个隐含于每一个类的非静态成员函数中的特殊指针(包括构造函数和析构函数),它用于指向正在被成员函数操作的对象。
this是一个指针常量,对于常成员函数,this同时又是一个指向常量的指针
new
对于基本数据类型,如果不希望在分配内存后设定初值,可以把括号省去。如:
int *point=new int;
保留空括号,表示用0对该对象进行初始化,如
int *point=new int();
用new建立一个类的对象时,如果该类存在用户定义的默认构造函数,则new T和new T()一样。若未定义默认构造函数,new T会调用系统生成的隐含的默认构造函数;new T()除了执行默认构造函数的操作外,还会为基本数据类型和指针类型的成员用0赋初值,且这一过程是递归的。
如果是用new建立的数组,用delete删除时在指针名前面要加“[ ]”
float (*cp)[25][10];
cp=new float[10][25][10];
vector数组对象的名字表示的就是一个数组对象,而非数组的首地址,因为数组对象不是数组,而是封装了数组的对象。
运算符重载
Clock& operator++(); //前置
Clock opeartor++(int); //后置
函数的返回值为一个引用类型,其作用是为了能够使函数返回值作为左值
#include<iostream>
using namespace std;
class Clock
{
private:
int x,y;
public:
Clock(int xx = 0,int yy = 0):x(xx),y(yy){}
void print()
{
cout<<x<<" "<<y<<endl;
}
Clock operator++() //运算符重载为成员函数
{
x++,y++;
return *this;
}
};
int main()
{
Clock m(10,20);
m.print();
(++m).print();
m.print();
}
//输出结果为:
//10 20
//11 21
//11 21
若将运算符如下重载为非成员函数,主函数不变。
class Clock
{
...
friend Clock operator++(Clock &m);
};
Clock operator++(Clock m)
{
m.x++;
m.y++;
return m;
}
则输出结果为:
10 20
11 21
10 20
即,仅++m的返回结果为自增后的对象,而m本身并未发生改变
将形参改为传递引用,则m也会发生变化,结果与前面一致。