C++ 阻止复制成员数据
C++ Prevent copy a member data
我有一个不寻常的情况,
假设我有一堂像下面的课,
template <typename T>
class C
{
public :
C (int size) : value_(size), some_other_member_(size) {}
T &value () {return value_;}
const T &value() const {return value_;}
private :
T value_;
SomeOtherType some_other_member_;
};
该类的设计使得客户端可以完全访问成员value_
,就像std::vector
的operator[]
会返回一个引用一样,这个类也必须通过返回一个引用来赋予客户端完全访问权限。二传手/吸气手对是不行的。
但是,与std::vector
不同,我不想让客户端能够完全替换成员。也就是说,客户应能够呼叫value_
的const
或非const
成员,但不允许以下情况:
C<SomeType> c(10);
SomeType another_value(5);
c.value() = another_value; // This shall not be allowed
有什么可能的方法可以让客户完全访问value_
。从某种意义上说,类C
应该像一个容器,但是一旦它包含的东西被初始化(通过构造函数,有T
的要求,但这在这里无关紧要),客户端只能通过T
的成员函数修改value_
,而不能通过赋值替换value_
。
但是,要求T
不可复制对我来说不是一个选择。因为类C
是可以复制的。问题的核心是,如类C
所示,C
有几个成员,它们都有一个size
属性,当构造时,它们都是用相同的size
构造的,如果允许通过赋值替换value_
,那么它允许数据结构被破坏,因为成员可能不再具有相同的size
属性。
要求T
仅在大小相同时才允许复制或分配也不是一种选择。因为,在复制C
对象时,源对象和目标对象之间的大小可能不同。例如
C c1(10);
C c2(20);
c1 = c2;
是完全合理的。c1
的大小已更改,但其所有成员也更改为相同的新大小,因此可以。
我希望我已经把问题说清楚了。我总结,我希望C
对T
没有太大的限制,T
基本上可以是任何具有所需构造函数的类型。 可以复制和分配T
。我不希望客户做的唯一瘦是分配给value_
通过C::value()
。
如果您希望用户能够在对象上调用非 const 成员函数,并且想要返回对实际对象的引用,则不能完全禁止赋值,因为赋值运算符基本上就是这样(您可以将a = b
重写为a.operator=(b)
)。因此,您要么只需要返回对对象的 const 引用,要么使包含的对象non_copyable
,要么接受可以分配给它的事实。
就个人而言,我建议重新考虑设计。即使你可以禁止赋值,也不能保证对象没有成员函数,它做的基本思考(.swap(...)
是一个典型的候选者),所以只要你允许调用非 const 成员函数,你就不会真正赢得任何东西。
但是,如果您只关心不允许意外分配,则可以使此类分配更加困难。如果T
不是内置的,则可以创建一个派生类,该类不会公开公共赋值运算符并返回对该运算符的引用:
template <typename T>
class C{
public :
class Derived: public T {
private:
Derived(int size):T(size) {}
Derived& operator=(const Derived&) = default; //used C++11 syntax for brevity, for C++03 code it has to be implemented here
Derived(const Derived&) = default; //don't want this class to be copyied outside of C
~Derived() = default;
friend class C;
};
C (int size) : value_(size), some_other_member_(size) {}
Derived& value () {return value_;}
const Derived& value() const {return value_;}
private :
Derived value_;
SomeOtherType some_other_member_;
};
这将通过继承为所有公共成员提供访问权限,但隐藏赋值运算符(和构造函数)。当然,如果您使用 c++11,则可以通过使用/定义移动构造函数/赋值和使用完美转发来增强此代码,以允许不同的构造函数。注意,派生的 T 部分仍然可以分配给使用static_cast<T&>(C.value()) = foo
;
为了支持无法派生的类型(内置...),您需要创建一个代理,该代理公开除赋值之外的所有功能。
至于你的getter/setter问题,我会写
const T& value() const; // as getter
void value(const T&); // as setter
返回const T&
(const-reference)完全反对c.value() = 10
等情况(参见例如。斯科特·迈耶斯的有效C++,第23项)。
我认为这也解决了复制问题:你的类仍然是可复制的。
- 嵌套在类中时无法设置成员数据
- 私有成员数据不可用于公共成员功能
- 我想知道我是否可以将一个类分配给特定的成员数据并创建该类的实例
- 类的成员数据未更新
- 为什么类成员数据必须是静态的才能被模板化类的模板化结构成员访问
- C++:成员不可访问-使用友元函数允许一个类修改另一个类的成员数据
- 如何高效更改向量中所有对象的成员数据?
- constexpr 偏移量,带有指向成员数据的指针
- 从其后声明的另一个成员数据初始化成员数据是否为未定义行为
- C++ 类析构函数删除部分但不是全部成员数据
- 初始化 MFC 中 CFormView 派生类的成员数据
- 覆盖复制/移动分配超载时,我是否需要删除当前的成员数据
- 根据参数设置构造函数的成员数据类型
- 对齐说明符:在类型 / 上 成员数据
- 如何实现ressize()以更改C 中动态成员数据的能力
- C++ 阻止复制成员数据
- 什么是成员数据指针的正确赋值语句
- C++ 在类中使用 strcmp() 处理私有成员数据
- 成员数据在stack实例上覆盖
- 初始化继承的成员数据