我试图更好地理解 const-correctness
是如何做到的工作,更具体地说,在处理其成员基于 containers
的类时和smart pointers
。
我猜想 const-correctness
无论类成员如何,属性都是相同的。然而,由于我很难清楚地了解发生了什么,
我决定向你寻求建议。
所以,这是上下文。我有一个ShapeContainer
具有作为私有(private)类成员的智能指针 vector 的类。
Shape
类是抽象的,具有以下虚函数 virtual float doSomething();
然后由其派生类重新定义。请注意,它是一个非常量类函数。
相关部分代码如下:
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 对象的引用如何调用非 const 函数呢?
第二季度。通过调用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();
时,我收到以下编译器错误:error C2662: 'ShapeInfo::doSomething' : cannot convert 'this' pointer from 'const ShapeInfo' to 'ShapeInfo &'
.
但是,当我添加 non-const
重载版本operator []
编译器错误消失了。那么,为什么我真的需要 non-const operator[]
对于 ShapeContainerInfo
而不是ShapeContainer
?
第四季度。如果m_vect
private
ShapeContainerInfo
的成员现在设置为public
成员且仅 operator[]
的常量版本已定义(不是non-const
),则没有编译器错误消息。为什么这个?例如设置后m_vect
成为公开课成员(member):float tmp = info.m_vect[i].doSomething();
Q5。我怎样才能正确定义 ShapeInfo
和ShapeContainerInfo
类,我只需要定义 const-version
operator[]
的并且仍然能够调用 float doSomething()
功能?
如果您对整个示例代码感兴趣,请查找 here .
随时欢迎澄清和建议:-)
谢谢!
最佳答案
问题1:shared_ptr是const,并不意味着指向的对象是const。为此,您需要 shared_ptr<const Shape>
.
Q2:由于您的 ShapeContainer 不是 const,所以非 const 函数更匹配,因此调用它而不是 const 版本。
Q3: vector 将其常量传播到其元素。 shared_ptr 没有。这与数组和原始指针的行为一致。 const 数组的元素是 const。 const 指针指向的东西(不一定)不是 const。
Q4:你是说这不会产生错误吗?
ShapeContainerInfo info;
info[0].doSomething();
请澄清,因为这应该是一个错误。
Q4:好的,所以你是说这不会产生错误:
ShapeContainerInfo info;
info.m_vect[0].doSomething();
也不应该。该 vector 不是 const。只有在 const 成员函数内部, vector (以及所有其他成员)才被视为 const。
Q5:使 m_vect 成为唯一指针的 vector 。在 const 函数内部, vector 本身将是 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;
};
关于c++ - 智能指针的 const 正确性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8793703/