c++ - 智能指针的 const 正确性

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

我试图更好地理解 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。我怎样才能正确定义 ShapeInfoShapeContainerInfo类,我只需要定义 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/

相关文章:

c++ - 为什么不继承 C++ 构造函数?

c++ - Windows 中 posix_memalign 的正确替代品是什么?

php - 带有 PHP 示例的一般多态性

html - 在厚重的文本页面上,包装器不会到达页面的最底部

c++ - 使用 Visitor 时更改容器

C++:线程间共享的静态函数成员,可以全部阻塞吗?

c++ - 使用 exit(1) 从函数返回

java - 强制继承类定义某些方法

java - java中的虚方法调用-多态性

c++ - 确定字符是否属于一组已知字符的最快方法 C++