4

我有一个成员变量 ,enabled_m其值取决于许多变量。由于这些不变量应该由类维护,我希望它是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;
};

哪个有效,但实际上我的意图是要求用户foo_t通过课程来修改 enabled_m. 如果用户只想阅读 enabled_m,那应该是允许的操作:

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

有没有一种方法可以enabled_m public进行const操作和privateconst操作,而无需用户通过访问器例程?

4

3 回答 3

10

大多数工程师会更喜欢您使用访问器方法,但如果您真的想要破解,您可以执行以下操作:

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;
    }
};
于 2014-10-31T17:21:14.100 回答
9

不,没有办法将修改仅限于成员。private限制对该名称的所有访问;const防止到处修改。

有一些怪诞的替代方案(如const引用或使用const_cast),但访问器函数是最简单和最惯用的方法。如果它是内联的,如您的示例所示,那么它的使用应该与直接访问一样有效。

于 2014-10-31T17:18:12.703 回答
5

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:

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:

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.

To make a long story short, this is usually a poor design. Just don't do it.

于 2014-10-31T17:31:30.047 回答