template <class T>
class deep_const_ptr
{
T * priv;
public:
deep_const_ptr(const deep_const_ptr & p_other); // copy ctor
T const * operator->() const;
T * operator->();
..... // other crap
};
void Cheese::doThings(const deep_const_ptr<Cheese> p_other)
{
deep_const_ptr<Cheese> awayGoesTheConst(p_other); // I don't want this to work.
awayGoesTheConst->doTerribleThings();
}
我想阻止复制构造从const到非const。
也许这甚至没有任何意义?
新的C ++ 11/14/17可以实现这一点吗?
编辑:
是的,问题是,如果我不给复制构造函数,STL容器就不会工作。而且我非常需要他们工作。
编辑:
deep_const_ptr是我在遇到STL容器和const对象问题时想出的解决方案。
class Shape
{
private:
std::list<Vertex *> m_vertices;
public:
virtual void std::list<Vertex*> * const getVertices() { return &m_vertices; }
virtual void std::list<Vertex const *> * const getVertices() const { return &m_vertices; } // doesn't work, cannot convert between different types of lists
}
我想从不可变形状提供不可变顶点对象。
我提出的两个解决方案是自定义deep_const_ptr指针类型和自定义列表
Vertex const *& operator[](unsigned int) const;
答案 0 :(得分:1)
我假设你所追求的是一个深度const指针实现以及如何处理它的复制。正如您已经发现的那样,一个简单的复制构造函数不会这样做,因为您将丢失指针上的const。没有其他方法可以禁止外部对象上的const删除,因此您只需要禁用复制构造函数。 现在你的问题的当前版本并不清楚为什么这是一个问题。从您的评论和上一个问题,我只能推断出你想在容器中使用指针,std :: vector&lt;&gt;特别。实现这项工作的关键是禁用复制,但启用移动(请注意,您需要rvalue-reference支持,这是C ++ 11的一部分):
template <class T>
class deep_const_ptr
{
T * priv;
public:
deep_const_ptr(const deep_const_ptr &) = delete; // Do not allow this!
deep_const_ptr& operator=(const deep_const_ptr &) = delete; // Nor this!
deep_const_ptr(deep_const_ptr &&) = default; // But this is okay
deep_const_ptr& operator=(deep_const_ptr &&) = default; // So is this!
T const * operator->() const;
T * operator->();
..... // other crap
};
容器通常只需移动而不是复制即可工作。
如果您确实需要对副本的支持,则需要将其用于仅支持const访问的其他类型。例如,您可以为deep_const_ptr
专门设置const T
,并且只在其中实现operator->
和operator*
的常量变量。此外,您允许通过转换运算符将deep_const_ptr“降级”为deep_const_ptr。但这意味着某种多个所有者处理,例如引用计数,所以我将把它遗漏掉。 const和非const版本的行为也不同,这也很奇怪,但这是你的决定。就个人而言,我建议坚持这一举动。
答案 1 :(得分:0)
修改编辑:您再次更新了答案,让我回复一下。
只需使用const
指针:
void Cheese::doThings(const Cheese* p_other)
{
Cheese* p = p_other; // compiler ERROR
p->doTerribleThings(); // can not do terrible things
}
或者如果你想要shared_ptr
:
void Cheese::doThings(const std::shared_ptr<const Cheese>& p_other)
{
std::shared_ptr<Cheese> p = p_other; // compiler ERROR
p->doTerribleThings(); // can not do terrible things
}
const ptr<T>
与ptr<const T>
不同。第一个表示无法更改的指针对象,而指向的对象可以。第二个表示可以更改的指针对象,但指向的对象不能。
对于函数签名void foo(const A a)
没有多大意义。你说&#34;给我一份副本,我保证不会改变它&#34;。谁在乎您对副本的处理方式?使用void foo(const A& a)
以避免创建副本。
修改强>:
我想允许复制nonconst - &gt; nonconst,nonconst - &gt;常量, const - &gt;常量。
已经为#&#34;正常&#34;指针T*
或std::shared_ptr
。
<强>旧强>:
只需使用T* operator->() const;
即可。如果存储的指针是非常量指针,如Cheese*
,它可以自动转换为const Cheese*
。
函数operator->()
被标记为const,因为它不会更改指针对象本身。这与存储的对象无关!
vector
的示例:
std::vector<Cheese*> a(10);
a[0] = 0; // does change a
Cheese* p = a[0]; // does not change a
a[0]->foo(); // still does not change a!
如果您希望deep_const_ptr
指向的对象为const,则必须使用deep_const_ptr<const Cheese>
。
vector
的示例:
std::vector<const Cheese*> a(10); // const pointer!
a[0] = 0; // does change a
const Cheese* p = a[0]; // does not change a
a[0]->foo(); // now this only works if Cheese::foo is const