一、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,无参,返回值类型为AA 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