【问题标题】:C++ Preventing const methods from changing data through a member pointer or referenceC++ 防止 const 方法通过成员指针或引用更改数据
【发布时间】:2015-02-26 00:55:51
【问题描述】:

假设我有一个像这样的简单类

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

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

有标准的解决方案吗?

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

【问题讨论】:

  • 有一个C++17的提案,propagate_const.
  • see herehere 一些选项
  • std::string 会按照你想要的方式行事。不知道为什么引用会编译,这对我来说似乎是错误的。
  • @MarkRansom 类可以有引用成员。 (它使隐式生成的构造函数为deleted)
  • 显示了一些非字符案例。我的意图是永远不会将其视为字符串,就像类型外部的东西而不是它所拥有的东西(所以不能是值类型,因为这是一个副本,并且 unique_ptr、shared_ptr 等具有与原始指针相同的 const 行为) .

标签: c++ c++11 constants const-correctness


【解决方案1】:

嗯,std::reference_wrapperstd::shared_ptr 都不提供 const 传播,因此它们并不比常规指针更“const-strict”。

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

我的提议是这个类:

#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;
};

所以这对你有用:

class Foo
{
public:
private:
    ConstPropagatedPointer<char*> str; 
    ConstPropagatedPointer<ComplexObj*> obj; 
    ConstPropagatedPointer<std::shared_ptr<ComplexObj>> obj2;
};

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-03-22
    • 2021-12-21
    相关资源
    最近更新 更多