一、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