在类中使用'const'和在C++中使用运算符重载是否有一个好的规则?
Is there a good rule for using 'const' in classes and operator overloads in C++?
我有一段这样的代码:
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。
这就引出了一个重要的问题:const
ness是病毒性的。如果将一个方法标记为const,那么它对自身调用的所有其他方法也必须是const。对const对象调用方法也是如此-只能调用const方法。如果你不从一开始就这么做,你可能会陷入这样的境地:使一个方法常量导致改变整个其他方法链,所以你更容易放弃。
为什么常量是好的:大多数错误都是由应用程序状态以意想不到的方式变化引起的——只要问问那些对不变性赞不绝口的函数式编程迷就知道了:)。const方法不能更改对象的状态,因此它消除了意外更改的可能性:例如,如果在const方法中间抛出异常,则可以确保对象不处于使类不变量无效的半修改状态。
现在,C++不仅仅是一种面向对象的语言,因此您可以通过其他方式更改应用程序状态,也可以滥用mutable
和const_cast
来欺骗编译器,但使用const
有助于编写正确的软件并降低调试工作量。
- 是否可以在C++中有一个"generic"模板参数,该参数可以是非类型模板参数或类型?
- 节点是否为空,即使它有一个值?
- 是否有一个 std::set 函数来确定不超过数字 x 的最大元素?
- 除了 std::vector 之外,是否有一个 std 容器不会复制和销毁作为类的元素?
- 是否有一个库可以检查C++中的变量类型?
- 是否有一个版本的glCopyImageSubData在Openg GL中使用混合?
- 是否已经有一个 constexpr std::bit_cast 与 g++ 一起使用
- 对于C字符串,是否有一个标准的C++迭代器
- 是否可以有一个模板函数,可以将向量和非向量类型都作为参数
- 是否有一个类似STL的函数来用索引的某个函数填充数组
- 是否有一个C++函数可以准确返回平方根反比的内置 CPU 操作 RSQRTSS 的值?
- 是否有一个标准函数可以打印/监视stdin文件的内容,同时将数据留在stdin中
- C++是否有一个容器,每个类型最多存储一个对象
- C++中是否有一个函数可以为您获取指向该节点的所有指针的地址空间
- 对于std::bitset,是否有一个ffs()等价物
- 是否有一个Windows驱动程序函数可以执行Windows文件api SeFileAttributes的等效功能
- 是否有可能有一个派生类继承最终函数但创建相同的函数(而不是重写)
- C 中是否有一个无法更改的时间戳?(Internet独立)
- 是否有一个很好的方法可以在C 11中打印出像JSON一样的Trie结构(仅迭代解决方案)的扁平命名空间
- 是否有一个函数可以显示我创建的类中的对象到 QTextBrowser 中?