在类中使用'const'和在C++中使用运算符重载是否有一个好的规则?

Is there a good rule for using 'const' in classes and operator overloads in C++?

本文关键字:有一个 是否 规则 和在 const C++ 运算符 重载      更新时间:2023-10-16

我有一段这样的代码:

class EducationalCentre
{
    string _centreName;
    vector<Course> _courses;    // courses offered by the Centre
    Collection<Course*, Student*, 150> _applicants;
public:
    EducationalCentre(string name="<name>")
    {
        _centreName = name;
    }
    EducationalCentre(const EducationalCentre& obj) 
        :_courses(obj._courses), _applicants(obj._applicants) 
    {
        _centreName = obj._centreName;
    }
};

现在,在这部分_applicants(obj._applicants)复制构造标头中,(obj周围有一条歪歪扭扭的红线,悬停在它上面,错误说明了类型不兼容(提到了const)。

既然我不想在这个阶段改变任何事情(这是考试的一部分),我想知道为什么会发生这种情况。

我试着从EducationalCentre(const EducationalCentre& obj)中删除const,这确实解决了问题,但。。正如我所说,我宁愿了解导致这种情况的原因,而不是删除它。

使用const的规则是尽可能使用它:)

当然,与所有最佳实践一样,也有例外,但通常情况下,如果非静态方法不会改变对象的状态,则应始终努力使其成为const

出现问题的原因是Collection复制构造函数对用作源对象的实例进行了非常数引用。

复制构造函数可以使用const或非常数引用作为其参数,但是,IMO,非常数只能在您别无选择的情况下使用,这种情况很少发生。基于另一个对象创建对象不应更改源对象,因此应将其标记为const

正如我在评论中所指出的,类是泛型的与复制ctor获取const引用无关。事实上,如果你看看例如std::vector,你会发现它有一个复制构造函数,它接受常量引用。您在参数的Collection副本构造函数中使用的一些方法可能是非常量的,这就是为什么您不能将参数设为常量的原因。解决方案是将有问题的方法也设为const。

这就引出了一个重要的问题:constness是病毒性的。如果将一个方法标记为const,那么它对自身调用的所有其他方法也必须是const。对const对象调用方法也是如此-只能调用const方法。如果你不从一开始就这么做,你可能会陷入这样的境地:使一个方法常量导致改变整个其他方法链,所以你更容易放弃。

为什么常量是好的:大多数错误都是由应用程序状态以意想不到的方式变化引起的——只要问问那些对不变性赞不绝口的函数式编程迷就知道了:)。const方法不能更改对象的状态,因此它消除了意外更改的可能性:例如,如果在const方法中间抛出异常,则可以确保对象不处于使类不变量无效的半修改状态。

现在,C++不仅仅是一种面向对象的语言,因此您可以通过其他方式更改应用程序状态,也可以滥用mutableconst_cast来欺骗编译器,但使用const有助于编写正确的软件并降低调试工作量。

相关文章: