一、const
C语言中const就是一个容易让人迷惑的关键字
1.const int p;
2.const int *p;
3.int const *p;
4.int *const p;
5.const int *const p;
6.int const *const p;
第一个好分辨是常量整数,后5个有一种较容易的辨别出来:从右向左,遇到p就换成“p is a”,遇到*就换成“point to”这样2就可以读作p is a point to int const(p是一个指向整型常量的指针);3可以读作p is a point to const int(p是一个指向常量整型的指针),就可以看出2和3是同一个意思;4可以读作p is a const point to int(p 是一个指向整型的常量指针);5就是p is a const point to int const(p是一个指向整型常量的常量指针);同理6也可以这样“翻译”出来,发现和5的意思相同。
- 成员变量调用成员函数
#include <iostream.h>
using namespace std;
class Date
{
public:
Date(int year,int month,int day)
{
_year = year;
_month = month;
_day = day;
}
void Show()
{
cout<<"call Show"<<endl;
cout<<_year<<"-"<<_month<<"-"<<_day<<endl;
}
void Show()const//const 修饰this指针指向的对象
{ cout<<"call const Show"<<endl;
cout<<_year<<"-"<<_month<<"-"<<_day<<endl;
}
private:
int _year;
int _month;
int _day;
};
int main()
{
Date d1(2018,3,28);
cout<<d1;
const Date d2(1900,1,1);
d2.Show();
system("pause");
return 0;
}
其中d1是没有用const修饰的对象被初始化为2018,3,28;d2是用const修饰的对象被初始化为1900,1,1。
运行得到的结果是
如果将没有const的成员函数屏蔽,运行得到的是
都调用了const修饰的成员函数,没加const的对象也可以调用。如果屏蔽了有const修饰的成员函数呢?
不能成功编译,说明const是一个将权限缩小的关键词,加了const权限就只能从可读可写变成只可读。所以上面的加了const的对象无法将权限扩大,就无法调用非const修饰的成员函数。
- 成员函数调用成员函数
#include <iostream>
using namespace std;
class Date
{
public:
Date(int year,int month,int day)
{
_year = year;
_month = month;
_day = day;
}
void ShowYear()const
{
cout<<"call ShowYear"<<endl;
cout<<"year = "<<_year<<endl;
}
void ShowMonth()
{
cout<<"call ShowMonth"<<endl;
cout<<"month = "<<_month<<endl;
}
void Show()
{
cout<<"call Show"<<endl;
cout<<_year<<"-"<<_month<<"-"<<_day<<endl;
ShowMonth();
ShowYear();
}
//void Show()const
//{
// cout<<"call const Show"<<endl;
// cout<<_year<<"-"<<_month<<"-"<<_day<<endl;
//
//}
private:
int _year;
int _month;
int _day;
};
int main()
{
Date d1(2018,3,28);
d1.Show();
//const Date d2(1900,1,1);
//d2.Show();
system("pause");
return 0;
}
运行结果:
class Date
{
public:
Date(int year,int month,int day)
{
_year = year;
_month = month;
_day = day;
}
void ShowYear()const
{
cout<<"call ShowYear"<<endl;
cout<<"year = "<<_year<<endl;
}
void ShowMonth()
{
cout<<"call ShowMonth"<<endl;
cout<<"month = "<<_month<<endl;
}
//void Show()
//{
// cout<<"call Show"<<endl;
// cout<<_year<<"-"<<_month<<"-"<<_day<<endl;
// ShowMonth();
// ShowYear();
//}
void Show()const
{
cout<<"call const Show"<<endl;
cout<<_year<<"-"<<_month<<"-"<<_day<<endl;
ShowYear();
ShowMonth();
}
private:
int _year;
int _month;
int _day;
};
int main()
{
Date d1(2018,3,28);
d1.Show();
//const Date d2(1900,1,1);
//d2.Show();
system("pause");
return 0;
}
编译报错显示“Date::ShowMonth()”不能将“this”指针从“const Date”转化为“Date &”
加上const的成员函数就不能将权限扩大即不能调用非const修饰的成员函数。
二、静态成员static
类的静态成员为所有对象所共有,无论定义多少个对象静态成员就只有一份;另外static成员并不是在类的定义中初始化的而是在类的定义外被初始化的。
- 静态成员函数访问非静态成员
class Date
{
public:
Date(int year,int month,int day)
{
_year = year;
_month = month;
_day = day;
++stime;
}
void ShowYear()const
{
cout<<"call ShowYear"<<endl;
cout<<"year = "<<_year<<endl;
}
void ShowMonth()
{
cout<<"call ShowMonth"<<endl;
cout<<"month = "<<_month<<endl;
}
static void Show()
{
cout<<"call Show"<<endl;
cout<<_year<<"-"<<_month<<"-"<<_day<<endl;//访问非静态成员
ShowMonth();//调用非静态成员函数
ShowYear();
}
static int PrintTime()
{
cout<<"time = "<<stime<<endl;
Date::Show();//静态成员函数的调用
return stime;
}
private:
int _year;
int _month;
int _day;
private:
static int stime;
};
int Date::stime = 0;//定义并初始化静态变量stime
int main()
{
Date d1(2018,3,28);
/*d1.Show();*/
Date d2(1900,1,1);//创建2个对象static成员只有一份
//d2.Show();
Date::PrintTime();
system("pause");
return 0;
}
运行结果发现不止一个错误:
- 反过来,用非静态成员函数访问静态成员函数会调用成功吗?
class Date
{
public:
Date(int year,int month,int day)
{
_year = year;
_month = month;
_day = day;
++stime;
}
void ShowYear()const
{
cout<<"call ShowYear"<<endl;
cout<<"year = "<<_year<<endl;
}
void ShowMonth()
{
cout<<"call ShowMonth"<<endl;
cout<<"month = "<<_month<<endl;
}
void Show()
{
cout<<"call Show"<<endl;
cout<<_year<<"-"<<_month<<"-"<<_day<<endl;//访问非静态成员
ShowMonth();//调用非静态成员函数
ShowYear();
Date::PrintTime();//调用静态成员函数
cout<<"stime is "<<Date::stime<<endl;//访问静态成员
}
static int PrintTime()
{
cout<<"time = "<<stime<<endl;
return stime;
}
private:
int _year;
int _month;
int _day;
private:
static int stime;
};
int Date::stime = 0;//定义并初始化静态变量stime
int main()
{
Date d1(2018,3,28);
d1.Show();
Date d2(1900,1,1);//创建2个对象static成员只有一份
system("pause");
return 0;
}
编译成功,结果正确。
非静态成员可以访问静态成员,反之不行。
三、内联inline
c语言中的宏在预编译时会在有宏的地方进行宏替换,没有压栈开销提高了效率和代码的复用性;缺点是不方便调试,没有类型检查,代码可读性可维护性下降。
例如
#define Swap(a,b)int tmp=a;a=b;b=tmp;
int main()
{
int x1 = 10;
int x2 = 20;
Swap(x1,x2);
int x3 = 30;
int x4 = 40;
Swap(x3,x4);//展开后出现tmp重命名
}
C++中也有类似宏的函数。
编译时编译器会在内联函数的地方展开,没有压栈开销提升程序运行的效率,所以《effctive c++》中就建议用const/枚举/内联替代宏。如果代码很长同时在很多地方展开或有递归就不宜使用内联。(别担心,自己定义为内联只是一个给编译器一个建议如果函数有递归或循环编译器就不会听你的建议)
定义在类内的成员函数默认定义为内联函数。
内联的定义和函数放在一起才是内联函数。
四、友元friend
友元分为友元类和友元函数。
以友元类为例:
class Date
{
friend ostream&operator<<(ostream &os,const Date &d);
public:
Date(int year,int month,int day)
{
_year = year;
_month = month;
_day = day;
++stime;
}
private:
int _year;
int _month;
int _day;
private:
static int stime;
};
ostream &operator<<(ostream &os,const Date &d)
{
cout<<"year = "<<d._year<<endl;
cout<<"month = "<<d._month<<endl;
cout<<"day = "<<d._day<<endl;
return os;
}
int Date::stime = 0;//定义并初始化静态变量stime
int main()
{
Date d1(2018,3,28);
cout<<d1;
//d2.Show();
//Date::PrintTime();
system("pause");
return 0;
}
将输出(<<)用友元函数重载就可以访问类中的私有成员。
但同时也破坏了C++的封装性。有点不懂为了封装起来运用了私有,但是为什么又用友元破坏了封装~