C++提供了关键字explicit,可以阻止不应该允许的经过转换构造函数进行的隐式转换的发生。声明为explicit的构造函数不能在隐式转换中使用。
C++中, 一个参数的构造函数(或者除了第一个参数外其余参数都有默认值的多参构造函数), 承担了两个角色。 1 是个构造器 ,2 是个默认且隐含的类型转换操作符。
所以, 有时候在我们写下如 AAA = XXX, 这样的代码, 且恰好XXX的类型正好是AAA单参数构造器的参数类型, 这时候编译器就自动调用这个构造器, 创建一个AAA的对象。
这样看起来好象很酷, 很方便。 但在某些情况下(见下面权威的例子), 却违背了我们(程序员)的本意。 这时候就要在这个构造器前面加上explicit修饰, 指定这个构造器只能被明确的调用/使用, 不能作为类型转换操作符被隐含的使用。
explicit构造函数的作用
解析:
explicit构造函数是用来防止隐式转换的。请看下面的代码:
class Test1 { public: Test1(int n) { num=n; }//普通构造函数 private: int num; }; class Test2 { public: explicit Test2(int n) { num=n; }//explicit(显式)构造函数 private: int num; }; int main() { Test1 t1=12;//隐式调用其构造函数,成功 Test2 t2=12;//编译错误,不能隐式调用其构造函数 Test2 t2(12);//显式调用成功 return 0; }
Test1的构造函数带一个int型的参数,代码23行会隐式转换成调用Test1的这个构造函数。而Test2的构造函数被声明为explicit(显式),这表示不能通过隐式转换来调用这个构造函数,因此代码24行会出现编译错误。
普通构造函数能够被隐式调用。而explicit构造函数只能被显式调用。
角度1: 就定义常量说的话, const 定义的常数是变量 也带类型, #define 定义的只是个常数 不带类型。
角度2: 就起作用的阶段而言,#define 是在编译的预处理阶段起作用,而 const 是在 编译、运行的时候起作用。
角度3: 就起作用的方式而言,#define 只是简单的字符串替换,没有类型检查。而 const 有对应的数据类型,是要进行判断的,可以避免一些低级的错误。 正因为 define 只是简单的字符串替换会导致边界效应,具体举例可以参考下面代码:
#define N 2+3 // 我们预想的 N 值是 5,我们这样使用 Ndouble a = N/2; // 我们预想的 a 的值是 2.5,可实际上 a 的值是 3.5
角度4: 就空间占用而言, 例如:
#define PI 3.14 //预处理后 占用代码段空间 const float PI=3.14; // 本质上还是一个 float,占用数据段空间
角度5: 从代码调试的方便程度而言, const 常量可以进行调试的,#define 是不能进行调试的,因为在预编译阶段就已经替换掉了
角度6: 从是否可以再定义的角度而言, const 不足的地方,是与生俱来的,const 不能重定义,而 #define 可以通过 #undef 取消某个符号的定义,再重新定义。
预处理 #define 变量定义值以后,不能用分号,否则就会计算错误,但是程序不会报错。
#define age 12 #define age1 10 #define age2 12; #define age3 10; int main() { int dd ; dd = age + age1; cout << "值=" << dd << endl; //值22 dd = age2 + age3; cout << "值=" << dd << endl; //值12 return 0; }
const 和 define 定义常量时,两个数的范围不同。
#include<cstdio> using namespace std; const int maxn=1e+10; int main() { printf("%d",maxn); return 0; }
然后输出是:
2147483647
如果用 define 定义的话:
#include<cstdio> #define maxn 1e+10 using namespace std; int main() { printf("%d",maxn); return 0; }
输出是:
536870912
但是,如果将输出的 %d 改为 %lld 的话,输出为:
4756540486875873280
那么,可以思考一下,如果将 const 的数据也改成 longlong 的话,输出为:
10000000000
刚好为我们想要的那个答案。
数据的范围还有输出的格式很重要!!!
常量实例:已知半径,求圆的周长和面积。
#include<iostream> using namespace std; #define PI 3.14 int main() { float radius = 10.0; float area = PI * radius * radius; float circumference = 2 * PI * radius; cout << "area is "<<area <<", circumference is "<< circumference<<endl; return 0; }
感谢您的支持,我会继续努力的!
支付宝扫一扫,即可进行扫码打赏哦
1854C++ 修饰符类型
C++提供了关键字explicit,可以阻止不应该允许的经过转换构造函数进行的隐式转换的发生。声明为explicit的构造函数不能在隐式转换中使用。
C++中, 一个参数的构造函数(或者除了第一个参数外其余参数都有默认值的多参构造函数), 承担了两个角色。 1 是个构造器 ,2 是个默认且隐含的类型转换操作符。
所以, 有时候在我们写下如 AAA = XXX, 这样的代码, 且恰好XXX的类型正好是AAA单参数构造器的参数类型, 这时候编译器就自动调用这个构造器, 创建一个AAA的对象。
这样看起来好象很酷, 很方便。 但在某些情况下(见下面权威的例子), 却违背了我们(程序员)的本意。 这时候就要在这个构造器前面加上explicit修饰, 指定这个构造器只能被明确的调用/使用, 不能作为类型转换操作符被隐含的使用。
explicit构造函数的作用
解析:
explicit构造函数是用来防止隐式转换的。请看下面的代码:
Test1的构造函数带一个int型的参数,代码23行会隐式转换成调用Test1的这个构造函数。而Test2的构造函数被声明为explicit(显式),这表示不能通过隐式转换来调用这个构造函数,因此代码24行会出现编译错误。
普通构造函数能够被隐式调用。而explicit构造函数只能被显式调用。
1853C++ 常量
角度1: 就定义常量说的话, const 定义的常数是变量 也带类型, #define 定义的只是个常数 不带类型。
角度2: 就起作用的阶段而言,#define 是在编译的预处理阶段起作用,而 const 是在 编译、运行的时候起作用。
角度3: 就起作用的方式而言,#define 只是简单的字符串替换,没有类型检查。而 const 有对应的数据类型,是要进行判断的,可以避免一些低级的错误。 正因为 define 只是简单的字符串替换会导致边界效应,具体举例可以参考下面代码:
角度4: 就空间占用而言, 例如:
角度5: 从代码调试的方便程度而言, const 常量可以进行调试的,#define 是不能进行调试的,因为在预编译阶段就已经替换掉了
角度6: 从是否可以再定义的角度而言, const 不足的地方,是与生俱来的,const 不能重定义,而 #define 可以通过 #undef 取消某个符号的定义,再重新定义。
1852C++ 常量
预处理 #define 变量定义值以后,不能用分号,否则就会计算错误,但是程序不会报错。
预处理 #define 变量定义值以后,不能用分号,否则就会计算错误,但是程序不会报错。1851C++ 常量
const 和 define 定义常量时,两个数的范围不同。
然后输出是:
如果用 define 定义的话:
输出是:
但是,如果将输出的 %d 改为 %lld 的话,输出为:
那么,可以思考一下,如果将 const 的数据也改成 longlong 的话,输出为:
刚好为我们想要的那个答案。
数据的范围还有输出的格式很重要!!!
1850C++ 常量
常量实例:已知半径,求圆的周长和面积。