繁体   English   中英

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::vectoroperator[]将返回引用一样,该类还必须通过返回引用赋予客户端完全访问权限。 设置器/获取器对将不起作用。

但是,与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属性,在构造时,如果允许value_通过赋值替换而被构造为相同的size , ,则在成员可能不再具有相同的size属性的意义上,它允许破坏数据结构。

要求T仅在大小相同时才允许复制或分配也是一种选择。 因为在复制C对象时,源和目标之间的大小可能会有所不同。 例如,

C c1(10);
C c2(20);
c1 = c2;

是完全合理的。 c1的大小已更改,但是其所有成员也都更改为相同的新大小,因此可以。

我希望我已经阐明了这个问题。 我总结一下,我希望CT不会造成太多限制, T基本上可以是具有所需构造函数的任何类型。 可以复制和分配T 我不希望客户端执行的唯一操作是通过C::value()分配给value_

如果您希望用户能够在对象上调用非const成员函数,并且希望返回对实际对象的引用,则不能完全禁止赋值,因为赋值运算符基本上就是这样(您可以重写a = b作为a.operator=(b) )。 因此,您只需要返回对您的对象的const引用,使包含的对象non_copyable或者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,则可以通过使用/定义移动构造函数/分配并使用完美的转发来增强此代码,以允许使用不同的构造函数。 注意,仍然可以使用static_cast<T&>(C.value()) = foo来分配Derived的T部分。

为了支持您不能从(buildins ...)派生的类型,您需要创建一个代理,该代理公开除赋值外的所有功能。

关于您的吸气剂/吸水剂问题,我会写

const T& value() const; // as getter
void value(const T&); // as setter

返回const T& (常量引用)恰好是针对c.value() = 10 (请参见例如Scott Meyers的Effective C ++,第23条)。

我认为这也解决了复制问题:您的课程仍然可以复制。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM