使用智能指针进行const正确性

时间:2012-01-09 19:02:45

标签: c++ polymorphism containers smart-pointers const-correctness

我试图更好地理解const-correctness如何工作,更具体地说,在处理其成员基于containerssmart 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[]函数(latterconst-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!

1 个答案:

答案 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;
};