C++中的const、静态成员、内联函数和友元

一、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的意思相同。

  • 成员变量调用成员函数
    C++中的成员函数也可以加上const,用来表示调用const修饰成员函数的对象不会被修改。
#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修饰的成员函数。

  • 成员函数调用成员函数
    非const成员函数Show()调用ShowMonth()和ShowYear()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;
}

    运行结果:




    反过来const成员函数Show()const调用Show Month()和ShowYear()const。
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++的封装性。有点不懂为了封装起来运用了私有,但是为什么又用友元破坏了封装~










  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值