C++ 类设计的问题小结

最近在做面向对象的研讨作业,在写代码时遇到一些令我抓狂的问题,在经过漫长的检查翻书搜索后总算都解决了。

下面把问题提取出来,做个记录。

比如说在类内定义了个运算符重载:

char & operator[](size_t x);

这个是为了能把返回值即当右值又当左值。但是,如果要在加const的参数上使用,则是不允许的:

void test(const (类名) & a){a[0];} // error

原因是当参数加const 后则不允许使用任何可能修改对象的功能,返回引用也不允许,即使你没有写出修改数据的语句

解决方案是再写个函数重载:

1 char & operator[](size_t x);
2 const char & operator[](size_t x) const//这里在后面也要加const 否者无法区别两函数的类型(不能用返回值区别)

这样就解决问题了!

==================================分割线===================================

还是更运算重载有关,看如下代码:

 1 class mystring
 2 {
 3 public:
 4     mystring() {};
 5     mystring(const mystring & a){}
 6     mystring& operator=(mystring &a){return *this;}
 7     mystring operator+(const mystring &a)
 8     {
 9         return a;
10     }
11 };
12 int main()
13 {
14    mystring a,b;
15    a+b;       //OK!
16    a=a+b;   //error
17 }

这段代码是不能编译的(在GCC下不行,可能在VC下可以),原因出在=号重载上。

由于+号返回的是个临时变量,它不能当左值 ,而等号的参数是个引用,可能可以被修改,所以非法。解决办法就是 参数声明为 const。

看来GCC的编译器语法检查的更严点,VC的包容性更好。

通过前两个例子,可以看出const 的威力所在,所以写代码时,能加const就加 const !

==================================分割线===================================

下面是个关于构造函数和 explicit 的问题:

 1 class mystring
 2 {
 3 public:
 4     explicit mystring(){}
 5     explicit mystring(const mystring & a){}
 6     mystring operator+(const mystring &a)
 7     {
 8         return a;
 9     }
10 };

这段代码无法编译。

问题是如果把第二个构造函数的explicit 禁止隐式转换 标记删了,编译就会正确,否则错误。

出错在+号重载里的 "return a;" 提示 no matching function for call to 'mystring::mystring(const mystring&)'

正常情况下 return a 调用的是 复制构造函数 ,但我已经写了而且参数类型对应。为什么还会错呢?

在return a的时候,编译器需要“偷偷地”地调用拷贝构造函数构造一个临时对象,而explicit关键字阻止了这种行为,所以编译出错。
加explicit的构造函数必须在程序里显式调用,连编译器自动调用的都不行。所以看来拷贝构造函数不能加explicit 。

 

原文地址:https://www.cnblogs.com/wuminye/p/2763304.html