Vir*_*721 9 c++ methods const class semantics
我不确定完全理解在类方法中使用的const关键字背后的哲学.
我一直认为在类方法的签名中使用const关键字意味着此方法不会修改它所调用的对象的字段.但是当我们使用例如一个向量时,operator []的重载不是const:
whateverT & vector<whateverT>::operator [] ( size_t pos )
Run Code Online (Sandbox Code Playgroud)
无论您对给定的引用做什么,它都不会对向量的字段执行任何修改,即使引用的项目被修改也是如此.
另一个例子 :
template<class T> class Array
{
T * _items;
T & operator [] ( size_t pos ) const
{
return _items[ pos ];
}
}
Run Code Online (Sandbox Code Playgroud)
我可以在这里使用const关键字,因为_items的值没有被修改(无论我们用它指向的是什么).对于编译器来说这是正确的,但如果我访问其中一个项并修改它,operator []将允许修改数组,即使它应该是const,即假设不修改数组的"内容".
在这种情况下该怎么办?使用或不使用const关键字?
谢谢 :)
AnT*_*AnT 14
这是你的设计决定的问题.Constness旨在用作设计概念.它应该帮助您实现您认为"修改"和"非修改"访问的更高级别的概念.通过const在类方法上正确使用,可以使"不可修改"的属性通过引用从一个对象传播到另一个对象.
"引用其他对象"可以表示至少两种不同的设计关系:
它可以用于实现聚合,在这种情况下,裁判被认为是引用者的组成部分.在这种情况下,通常应该强制执行对完整对象的所有部分的访问的常量:如果引用者是常量,则裁判也应该被认为是常量.您有责任通过对类的界面进行适当的限定来强制执行后者.
为了支持这个概念,你通常不会尝试修改const引用者方法内的裁判(即使它是正式的可能).反过来说:如果引用者的某些方法修改了裁判的内容,你就不应该声明该方法const(即使它是正式的可能).此外,const引用者的方法永远不应该向裁判返回非常量引用.
在这种情况下,外界甚至不应该知道聚合对象是通过引用存储的.这只是一个实现细节.对于外部世界,一切看起来好像聚合对象是引用者的直接直接成员.
这正是你观察到的情况std::vector.它的设计方式是确保整个向量的常量传播到向量元素的常量.为了实现它,它实现了两个版本的运算符[]
reference operator[]( size_type pos );
const_reference operator[]( size_type pos ) const;
Run Code Online (Sandbox Code Playgroud)它可用于实现不暗示聚合的纯引用.在这种情况下,裁判被认为是一个完全独立的,无关的对象.推荐人的常数不应传播给裁判.在这种情况下,可以const在引用者的方法中修改裁判.可以从引用者的const方法返回对裁判的非常量引用.
这种设计的一个例子是标准的智能指针:一个指针指到指针对象,但指针常量性不以任何方式暗示指针对象的常量性.例如,std::shared_ptr只有一个版本的运算符*
T& operator*() const;
Run Code Online (Sandbox Code Playgroud)
声明的它const返回对指向对象的非常量引用.