C++防止const方法通过成员指针或引用更改数据

Fir*_*cer 12 c++ const const-correctness c++11

说我有一个像这样的简单类

class Foo
{
public:
    void foo()const
    {
        str[5] = 'x';
        obj->changeTheWorld();
        x = 4;
        y.get() = 5;
        obj2->changeTheWorld();
    }
private:
    char *str; //some referenced data, not owned by Foo
    ComplexObj *obj; //some referenced data, not owned by Foo
    int &x; //references as well
    //wrapped reference, but has a "T& get()const"
    std::reference_wrapper<int> y;
    //an occasionally useful pointer wrapper for complex memory cases
    //but has a "T* get()const"
    std::shared_ptr<ComplexObj> obj2;
};
Run Code Online (Sandbox Code Playgroud)

这是有效的,因为在const方法中,它只是指针本身变为const,而不是它指向的数据.但是在许多情况下,这不是我想要的,如果const方法试图改变这些成员内容(直接或通过在该成员上调用非const方法),我想要编译错误.

有没有标准的解决方案?

我认为某种包装类应该能够实现这一点,并且也应该是编译器优化的东西,尽管还没有坐下来尝试设计这样的东西来覆盖所有的情况下给出一个strong_const<char*> strstrong_const<int&>(也不确定)一个好名字......).

Pio*_*ycz 4

好吧,两者std::reference_wrapper都不std::shared_ptr提供 const 传播,因此它们并不比常规指针更“const-strict”。

我建议创建您自己的 const 传播类(我不确定 - 也许 boost 已经提供了类似的东西 - 请在评论中告诉我)

我的建议是这门课:

#include <memory> // for pointer_traits

template <typename Pointer>
class ConstPropagatePointer 
{
public:
    using element_type = typename std::pointer_traits<Pointer>::element_type;
    using pointer = typename std::pointer_traits<Pointer>::pointer;
    using const_pointer = element_type const * const;
    using reference = element_type&;
    using const_reference = element_type const&;

    ConstPropagatePointer(Pointer ptr) : ptr(ptr) {}
    pointer operator -> ()
    {
        return &(*ptr);
    }
    const_pointer operator -> () const
    {
        return &(*ptr);
    }
    reference operator * ()
    {
        return *ptr;
    }
    const_reference operator * () const 
    {
        return *ptr;
    }
private:
    Pointer ptr;
};
Run Code Online (Sandbox Code Playgroud)

所以这对你有用:

class Foo
{
public:
private:
    ConstPropagatedPointer<char*> str; 
    ConstPropagatedPointer<ComplexObj*> obj; 
    ConstPropagatedPointer<std::shared_ptr<ComplexObj>> obj2;
};
Run Code Online (Sandbox Code Playgroud)