重载类型转换1
前言
在类型转换重载函数前加explicit
关键字可以限制该函数禁止使用隐式转换[c++11标准]explicit operator int();
在正常类型直接,比如float x 等于一个 int类型的变量,就会自动发生隐式转换简称隐转,目前就是当类型不同时方便运算。
规则好像就是整数由小转大,整数和浮点数比较转浮点。
正文
1 |
|
编译器给了报错
愿意在于,我们有两个重载,编译器就不能判断是把b1转成int还是把后面的100转成Box类型。
毕竟两种结果肯定不相同。
然后屏蔽的方法也就是说的关键字explicit
。给其中一个做限制。
1 | class Box{ |
做了隐转的限制之后,就能成功运行了,它会自动匹配到加法的重载。
注意:explicit只是限制隐式转换,如果还是想要转换就直接强转就行了
比如说:
所以说explicit
关键字重点就是限制类的operator重载时发生隐式转换。
至于放在哪个函数都无所谓,比如构造函数。
1 |
|
因为构造函数无法隐转,所以当下面这种计算的时候,需要手动将100强转成Box类型。
修订hstring之前的问题再继续
1 | hstring str; |
operator+重载是实现了,但是+完又赋值给str,就相当于str += 123;
但是cmd能看到输出了23,说明不是完全的错误,可能是内存的问题。
就得回到operator+定义的地方看看。
在此之前,hstring str;
是调用了构造函数
1 | hstring(char ch = 0x32); |
这个是没问题的,因为没有手动传值,他就用默认的设置缓冲区开辟一个。
1 | hstring &hstring::operator+(int _val){ |
我们的hsLen一开始如果没有传值,他初始化就是0。unsigned short hslen = hsLen + 12 - len - 1;
这段倒还好,0+12-len-1。memcpy(this->c_str + hsLen - 1, str + len, 12 - len);
但是这里就出现问题了,我们的c_str初始化是0x32的长度,hsLen - 1 就是 0 - 1. 说明写入的时候就从c_str[-1]开始写。。。
这样一搞写到前面去了就崩了,不符合逻辑了。
所以要学类那样,即便是空的,也要给他一个字节区分开内存。
这里就是空的初始化时长度要为1。
1 | hstring::hstring(char ch){ |
这样就不会有事了。
但是相反,有传值构造的时候,就要先把长度重置了。
然后是另一个加法问题
1 | hstring str; |
这种情况,str一开始是”123”字符串了,那么当str+123的时候,它是选择将后者隐转,还是前者隐转。
毕竟两个值截然不同,一个“123123” 一个 123+123
当然这里肯定就一种情况,是我们之前写好的operator+
所以还不够,我们要写一个构造函数,让int变成我们的hstring。
1 | hstring(int _val); |
1 | hstring::hstring(int _val):hstring(){ |
从数字转char的写法就直接套之前operator的了。
结果反正一样的。
构造函数完成了,就可以去触发之前说的隐转bug了。
不过要先注释掉operator+的方法。
1 | //hstring &operator+(int _val); |
注释完就能看到报错了,不过跟预期的有出入。
还要对右值进行一个操作,这里就是重载一次
1 | hstring &operator+(const hstring &&str); |
改成这样差不多了。
加右值引用是因为后面的常量内存是临时的,要想办法能够兼容。
就是之前的问题,是前者隐转还是后者隐转。
不需要隐转的时候就在前面加关键字explicit operator int();
然后就出现了另一个问题。不存在从hstring转换到int的构造。
单独拿出来相加可以,说明是相加之和得到了hstring类型的值。
那么就很简单。。强制转换一下。
然后就然后行得通了。
还有一些其它地方优化听的有点绕了,下次一定
结语
总体上搞了一个半吊子不到的string
运算符重载还是要小心吧,毕竟你只是解决了一种情况,还有很多种情况还需要额外的重载。周而复始看着有点绕。