我试图更好地理解const-correctness
如何工作,更具体地说,在处理其成员基于containers
和smart pointers
的类时。
我想无论班级成员如何,const-correctness
属性都是一样的。但是,由于我很难清楚地了解发生了什么,
我决定向你征求意见。
所以,这是上下文。我有一个ShapeContainer
类,它具有作为私有类成员的智能指针向量。
Shape
类是抽象的,具有以下虚函数virtual float doSomething();
,然后由其派生类重新定义。请注意,它是一个非const类函数。
代码的相关部分如下:
class ShapeContainer{
public:
typedef std::shared_ptr<Shape> ShapePtr;
typedef std::vector<ShapePtr> ShapePtrContainer;
// .......
const ShapePtr & operator[]( int ) const { return m_vect[index]; }; // const version
// ShapePtr & operator[]( int ) { return m_vect[index]; }; // non-const version
// .......
private:
ShapePtrContainer m_vect;
};
class Shape{
public:
// ...
virtual float doSomething() = 0;
};
以下是我的问题。
Q1。为什么我可以通过以下方式拨打doSomething()
功能:int index = 0; float tmp = container1[index]->doSomething();
(拥有ShapeContainer container1=createBasicShapes();
)?
根据我的理解,在调用const ShapePtr operator[] const
函数后,我们将获得指向const
对象的Shape
指针,但是doSomething()
虚拟对象
函数是不是 const。那么,对const-object的引用如何调用非const函数?
Q2。通过添加doSomething()
float tmp =container1[index]->doSomething();
版non-const
来调用operator[]
函数(latter
)和,const-version
然后调用重载版本而不是ShapeContainer
版本。为什么会这样?
现在,我现在没有ShapeContainerInfo
课程,而是一个名为vector
的新班级,但仍有ShapeInfo
但中级class ShapeContainerInfo{
public:
typedef std::vector<ShapeInfo> ShapeContainer;
const ShapeInfo & operator []( int index) const { return m_vect[index]; };
// ShapeInfo & operator []( int index) { return m_vect[index]; }; // non-const version
private:
ShapeContainer m_vect;
};
class ShapeInfo{
public:
typedef std::shared_ptr<Shape> ShapePtr;
// ...
float doSomething(){ return m_ShapePtr->doSomething(); };
private:
ShapePtr m_ShapePtr;
int m_nID;
};
班级(它有一个智能指针作为类成员)。
float tmp = container2[i].doSomething();
Q3。当我调用error C2662: 'ShapeInfo::doSomething' : cannot convert 'this' pointer from 'const ShapeInfo' to 'ShapeInfo &'
时,我收到以下编译器错误:non-const
但是,当我添加重载operator []
的{{1}}版本时,编译器错误就消失了。那么,为什么我真的需要non-const operator[]
ShapeContainerInfo
而不是ShapeContainer
?
Q4。如果m_vect
的{{1}} private
成员现在设置为ShapeContainerInfo
成员且仅,则定义public
的const版本(不是operator[]
),没有编译器错误消息。为什么这个?例如将non-const
设置为公共类成员后:m_vect
Q5。如何正确定义float tmp = info.m_vect[i].doSomething();
和ShapeInfo
类,以便我只需要定义ShapeContainerInfo
的{{1}}并仍然可以调用const-version
功能?
对于那些对整个示例代码感兴趣的人,请找到它here 澄清,建议总是受欢迎:-) 的Merci!
答案 0 :(得分:3)
Q1:shared_ptr是const,这并不意味着指向的对象是const。为此你需要shared_ptr<const Shape>
。
Q2:由于你的ShapeContainer不是const,非const函数是一个更好的匹配,所以它被调用而不是const版本。
Q3:向量将其常量传播到其元素。 shared_ptr没有。这与数组和原始指针的行为一致。 const数组的元素是const。 const指针指向的东西不是(必然)const。
问题4:你是说这不会产生错误吗?
ShapeContainerInfo info;
info[0].doSomething();
请澄清,因为那应该是一个错误。
问题4:好的,所以你说这不会产生任何错误:
ShapeContainerInfo info;
info.m_vect[0].doSomething();
也不应该。向量不是常量。仅在const成员函数内部,向量(和所有其他成员)被视为const。
问题5:使m_vect成为唯一指针的向量。在const函数内部,向量本身将是const,而唯一指针将是const。但是唯一指针指向的对象将是可变的。
例如,此类中的set函数不合法:
struct Foo
{
void set(int index, int value) const
{
v[index] = value;
}
std::vector<int> v;
};
但是这个是:
struct Foo
{
void set(int index, int value) const
{
*v[index] = value;
}
std::vector<std::unique_ptr<int>> v;
};