第一版的CMyString是这样的
class CMyString{
public:
CMyString(char c):m_data(1,c){
}
。。。。。。
private:
std::string m_data;
};
问题很大,有人这样用: CMyString str = 3.14f; 引入很大的隐藏bug。这样的地方有几十处,短时间内无法分析和修改完。
注: 错误是由这条路线进入的 double(3.14f) ==> char(3) ==> CMyString(char(3)) 。
第二版解决了这个问题,关键是:explicit
class CMyString{
public:
explicit CMyString(char c):m_data(1,c){
}
。。。。。。
private:
std::string m_data;
};
问题是加入这句话后,编译器把错误都成功的找出来了,但是项目进行不下去了,因为大家都编译不过了。
只能改进为第三版
class CMyString{
public:
explicit CMyString(char c):m_data(1,c){}
__declspec (deprecated(L"CMyString(double)废弃了")) CMyString(double f){
char buff[32]={0};
sprintf(buff,"%f",d);
m_data = buff;
}
。。。。。。
private:
std::string m_data;
};
有两个好处:1)不影响开发 2)错误是以警告形式给出的。但是仍旧出问题了
有一个函数 int CMyString::Find(const CMyString& str);
调用 str.Find('c'); 总是不能找到。分析一下原来是这样的:
因为Find需要CMyString参数,但是你给了一个char,但是又不允许隐式的调用构造函数,只能按下面的路线走了:
char('c') ==> double(99) ==> CMystring( double(99))
而且没有任何编译警告!经检查,是开发者(就是我)根本没有关注为什么没有报编译警告(即使已经发现没有一个地方报警告)
经检查,原来是项目把编译警告4996屏蔽了!!!#pragma warning( disable : 4996 )
总结:1)本着存疑必究的态度,不放过任何一个可疑点,才能做好一件事情
2)及时清理错误代码,不要做拐弯太多的设计(如本例的CMyString),回归到正常路径上来。