C++5-explicit、const的用法、mutable、常成员函数构成重载、在主函数中修改m_i的值

一、explicit的使用

explicit作用:

明确确定构造函数只能构造对象

代码示例:

class A
{
public:
	A(int i = 0):m_i(i){cout<<"A"<<i<<endl;}//构造函数可以用作类型转换,将int转换成类对象
	//explicit A(int i = 0):m_i(i){cout<<"A"<<i<<endl;}//explicit,明确确定构造函数只能构造对象

	void print(){cout<<m_i<<endl;}
private:
	int m_i;
};

void main()
{
	A c();     //为声明函数c,无参,返回值类型为A
	A d;       //定义无参对象,如果要定义无参对象,那么一定不能带()
	A a(5);    //为正常的调用

	//相当于用7去初始化b,被编译器优化了,编译器会声明一个无名对象
	//因此构造函数可以用作类型转换
	//加了explicit,就不能通过,会报错,可以避免这种现实的表达式出现
	A b = 7;

	a.print();
	b.print();
}

运行结果:

在这里插入图片描述

加了explicit后,运行 A b = 7; 会报错:

在这里插入图片描述

二、const的用法

const 作用
在C中是只读,在C++中是常量

1、const 可以定义常量

例如:const int a=10;

//注意,必须在声明的时候初始化
在这里插入图片描述

2、const 可以定义指针

可以定义不同的对象:
指针本身
指针所指向的内容

void main()
{
	int a=10;
	const int *p1 = &a; //p1本身是指针变量,所指向的内容不能修改,
	//注意a本身是能改的,可以通过改变a的值去改变*p1的值;但*p1不能,不能通过*p1去改变a的值。
	int const *p2 = &a; //同上
	int *const p3 = &a; //const 修饰p3本身。可以通过*p3改变a的值;p3本身是常量,不能改变。
	const int *const p4 = &a; //p4本身和所指向内容都不能修改
	/*
	cout<<*p1<<endl;
	a = 20;
	cout<<*p1<<endl;
	//(*p1)++;
	p1++;
	p2++;
	*/

	*p3 = 20;
	//p3 =&b;//要修饰p3本身
	cout<<a<<endl;
}

3、const 可以修饰函数的形参 – 提高函数的可读性和健壮性

例如:strcmp、strcpy
在这里插入图片描述

int strcmp(const char *str1,const char *str2)  //字符串比较
//字符串比较,不能对值进行修改
char *strcpy(char *dest,const char *src)      //执行字符串的拷贝
//可以通过const的使用,一眼看出是将*str2内的内容拷贝到*str1内

//dest本身就表示目的字符串,src表示原字符串
相关笔试题:
char *strcpy(char *dest,const char *src)

题目为:第一个dest代表的是目的字符串的首地址,为什么还需要函数返回值(返回值是目的字符串的首地址)
为什么不是

void mystrcpy(char *dest,const char *src);

答:实习链式表达式,什么意思呢:将这个函数的整体作为另外一个函数的参数去实现,又或是可以将其实现为表达式的右值;
例如:

cout<<strlen(strcpy(p,"123456"))<<endl;

//否则为
strcpy(p,"123456");
strlen(p);


4、cosnt可以修饰成员函数 — 放在函数参数的外面 — 常成员函数 — 在当前函数中不能修改本类数据成员的值

例如:

class A
{
public:
	void get()const{}
private:
}
	

一般情况下将 get函数、打印函数等这类函数设置为const

示例代码:

class A
{
public:
	A(int i = 0,int j = 0):m_i(i),m_j(j){}
	void Print()
	{
		cout<<m_i<<" "<<m_j<<endl;
	}
	//只是想要获取m_i的值,不能去修改
	int GetI()const //称其为常成员函数(什么意思呢:在当前函数中不能修改本类数据成员的值,即为在当前函数中不能修改m_i和m_j)
	{
		//m_i = 10;//error,在此函数(GetI)中不能修改
		return m_i;
	}
	int GetJ()const //
	{
		return m_j;//常成员函数
	}
private:
	int m_i;
	int m_j;
};
void main()
{
	A a(4,7);
	//cout<<a.m_i<<a.m_j<<endl;//error,m_i和m_j是private私有的

	//假设只想输出m_i(一般情况下实现打印函数,会将成员都打印)
	cout<<"a.m_i = "<<a.GetI()<<endl;//可行

}

运行结果:
在这里插入图片描述

三、mutable

使得其定义的类成员,可以在常成员函数内进行修改

class A
{
public:
	A(int i = 0,int j = 0):m_i(i),m_j(j){}
	void Print()const
	{
	    m_i = 100;
		cout<<m_i<<" "<<m_j<<endl;
	}
private:
	mutable int m_i;
	int m_j;
};
void main()
{
	A a(4,7);
	a.Print();
}

运行结果:

在这里插入图片描述

4、常成员函数构成重载

示例代码:

class A
{
public:
	A(){}
	void fn()const
	{
		cout<<"fn const"<<endl;
	}
	void fn()
	{
		cout<<"fn"<<endl;
	}
};
void main()
{
	const A a;
	A b;
	a.fn();
	b.fn();
}

运行结果:
在这里插入图片描述

5、如何在主函数中修改m_i的值

思路:返回引用

	int& GetI_1()  //返回的是m_i本身
	{
		return m_i;
	}
	const int& GetI_2()
	{
		return m_i;
	}

示例代码:

class A
{
public:
	A(int i = 0):m_i(i){}
	void Print()
	{
		cout<<"m_i = "<<m_i<<endl;
	}
	/*int GetI()
	{
		return m_i;
	}*/
	int& GetI_1()  //返回的是m_i本身
	{
		return m_i;
	}
	const int& GetI_2()  //加了const后就不能进行修改,只能获取m_i的值
	{
		return m_i;
	}
private:
	int m_i;
};
//思考--想在主函数中修改m_i的值
void main()
{
	A a(6);
	a.Print();
	//a.m_i = 7;//error
	//a.GetI() = 7;
	cout<<"修改"<<endl;
	
	a.GetI_1() = 7;
	a.Print();

	//a.GetI_2() = 8;//error,加了const后就不能进行修改,只能获取m_i的值
	cout<<a.GetI_2()<<endl;
}

运行结果:

在这里插入图片描述

加了const后就不能进行修改,只能获取m_i的值

a.GetI_2() = 8;//error

在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值