简体   繁体   English

是否可以仅为const操作指定一个私有成员变量public?

[英]Is it possible to specify a private member variable public only for const operations?

I have a member variable, enabled_m , whose value is dependent on a number of variables. 我有一个成员变量enabled_m ,其值取决于许多变量。 Since these invariants should be maintained by the class, I want it to be private : 由于这些不变量应该由类维护,我希望它是private

class foo_t
{
public:
    void set_this(...); // may affect enabled_m
    void set_that(...); // may affect enabled_m
    void set_the_other_thing(...); // may affect enabled_m

    bool is_enabled() const { return enabled_m; }

private:
    bool enabled_m;
};

Which works, but really my intent is to require a user of foo_t to go through the class to modify enabled_m . 哪个有效,但我的意图是要求foo_t的用户通过该类来修改 enabled_m If the user wants to just read enabled_m , that should be an allowable operation: 如果用户只想读取 enabled_m ,那应该是允许的操作:

bool my_enabled = foo.enabled_m; // OK
foo.enabled_m = my_enabled; // Error: enabled_m is private

Is there a way to make enabled_m public for const operations and private for non- const operations, all without having to require a user go through accessor routines? 有没有办法使enabled_mconst操作publicprivateconst操作,所有这些都不需要用户通过访问器例程?

Most engineers will prefer that you use accessor methods, but if you really want a hack-around, you could do something like this: 大多数工程师都希望你使用访问器方法,但如果你真的想要一个hack-around,你可以这样做:

class AccessControl
{
private:
    int dontModifyMeBro;
public:
    const int& rDontModifyMeBro;
    AccessControl(int theInt): dontModifyMeBro(theInt), rDontModifyMeBro(dontModifyMeBro)
    {}

    // The default copy constructor would give a reference to the wrong variable.
    // Either delete it, or provide a correct version.
    AccessControl(AccessControl const & other): 
        dontModifyMeBro(other.rDontModifyMeBro), 
        rDontModifyMeBro(dontModifyMeBro)
    {}

    // The reference member deletes the default assignment operator.
    // Either leave it deleted, or provide a correct version.
    AccessControl & operator=(AccessControl const & other) {
        dontModifyMeBro = other.dontModifyMeBro;
    }
};

No, there's no way to restrict modification only to members. 不,没有办法只限制成员修改。 private restricts all access to the name; private限制对该名称的所有访问; const prevents modification everywhere. const阻止了各地的修改。

There are some grotesque alternatives (like a const reference, or use of const_cast ), but the accessor function is the simplest and most idiomatic way to do this. 有一些奇怪的替代品(如const引用,或使用const_cast ),但访问器功能是最简单和最惯用的方式。 If it's inline, as in your example, then its use should be as efficient as direct access. 如果它是内联的,如在您的示例中,那么它的使用应该与直接访问一样有效。

A great deal here depends upon the intent behind exposing the enabled state, but my general advice would be to avoid exposing it at all . 这里的一个很大取决于背后暴露启用状态的意图, 我一般建议是避免暴露它

The usual use of your is_enabled would be something like: 通常使用你的is_enabled会是这样的:

if (f.is_enabled())
    f.set_this(whatever);

In my opinion, it's nearly always better to just call the set_this , and (if the client cares) have it return a value to indicate whether that succeeded, so the client code becomes something like: 在我看来,调用set_this几乎总是更好,并且(如果客户端关心)让它返回一个值来指示是否成功,所以客户端代码变成如下:

if (!f.set_this(whatever))
   // deal with error

Although this may seem like a trivial difference when you start to do multi-threaded programming (for one major example) the difference becomes absolutely critical. 虽然当你开始进行多线程编程时,这似乎是一个微不足道的差异(对于一个主要的例子),差异变得绝对至关重要。 In particular, the first code that tests the enabled state, then attempts to set the value is subject to a race condition--the enabled state may change between the call to is_enabled and the call to set_this . 特别是,测试启用状态,然后尝试设置值的第一个代码受竞争条件的影响 - enabled状态可能会在调用is_enabled和调用set_this之间发生变化。

To make a long story short, this is usually a poor design. 长话短说,这通常是一个糟糕的设计。 Just don't do it. 只是不要这样做。

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

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