强制在同一类中使用 Getter / Setter (C++)

发布于 2024-12-01 05:37:53 字数 557 浏览 1 评论 0原文

C++ 中有没有办法强制在类中使用 getter 或 setter?

class C{
   private:
   int x;        // should only be Changed by setX();

   private:
   setX(int i){
       (...)     // enforce some complicated invariantes
       x = i;
   };

   m(){
      x = 5;     // should not not allowed
   }
}

我唯一想到的是将所有超级私有成员作为私有变量放入具有受保护的 getter/setter 的抽象基类中。

但这听起来并不是一个好的做法。

是否有更常见的方法或约定来确保每个人都使用设置器?

(我的目的: 如果类变得更大,我发现很难记住哪些变量带有不变量。目前,在设置任何变量之前,我会搜索是否创建了 getter 或 setter(以了解我是否必须考虑不变量)。但我想摆脱这种不专业的搜索每次。)

Is there a way in C++ to enforce the use of getters or setters WITHIN the class?

class C{
   private:
   int x;        // should only be Changed by setX();

   private:
   setX(int i){
       (...)     // enforce some complicated invariantes
       x = i;
   };

   m(){
      x = 5;     // should not not allowed
   }
}

The only thing that comes to my mind is to put all the super-private members as private variables into an abstract base class with protected getters/setters.

But that doesn't sound like good practice.

Are there any more common ways or conventions to ensure, that everyone uses the setters?

(My purpose:
If the class gets bigger i find it hard to remember what variables carry invariants with them. And currently before setting any variable I search, whether I created a getter or setter (to find out whether i have to consider invariants). But i want to get rid of this unprofessional searching-each-time.)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

时间海 2024-12-08 05:37:53

你可以利用这样的组合:

class C_int
{
public:
    void setX(int i)
    {
        /* enforce invariants */
        x = i;
    }

private:
    int x;
};

class C
{
pulbic:
    void m()
    {
        x.setX(5);
        // x.x = 5; // Won't compile.
    }

private:
    C_int x;
};

但我觉得奇怪的是,这对你来说是一个实际问题,恕我直言。您是 C 类及其成员的编写者。您可以控制 x 变量的读/写方式,并且 x 不是该类的公共接口的一部分。虽然其他人(例如维护人员)确实可以编写将来破坏不变量的代码,但单元测试应该能够涵盖这些情况。

You can take advantage of composition like this:

class C_int
{
public:
    void setX(int i)
    {
        /* enforce invariants */
        x = i;
    }

private:
    int x;
};

class C
{
pulbic:
    void m()
    {
        x.setX(5);
        // x.x = 5; // Won't compile.
    }

private:
    C_int x;
};

But I find it odd that this is an actual problem for you, IMHO. You're the writer of the C class and its members. You have control over how the x variable is read/written, and x is not part of the public interface of the class. While it is true that other people (e.g. maintainers) can write code that breaks invariants in the future, unit tests should be able to cover those cases.

牛↙奶布丁 2024-12-08 05:37:53

a) 在整个代码库中支持访问器以保持一致性。那么您将更容易发现对会员的直接访问。如果您需要特殊的访问器,则创建特殊的方法:

void setFoo(const t_foo& foo) {
    assert(foo.isValid());
    this->d_foo = foo;
}

void invalidateFoo() {
    this->d_foo = t_foo::InvalidFoo();
}

b)得到答案:我经常会创建一个内部类(在某些情况下是暂时的):

class C {
    class t_inner {
    public:
    /* ... */
        void setX(int arg) {
            /* enforce some complicated invariants... */
            this->x = arg;
        }
        const int& getX() const {
            /* ... */
            return this->x;
        }
    private:
        int x;
    };
public:
/* ... */
private:
/* ... */
    void m() {
        this->inner().setX(5);
    }
private:
    t_inner d_inner;
};

a) favor accessors throughout your codebase for consistency. then you will more easily spot direct accesses to members. if you need special accessors, then create special methods:

void setFoo(const t_foo& foo) {
    assert(foo.isValid());
    this->d_foo = foo;
}

void invalidateFoo() {
    this->d_foo = t_foo::InvalidFoo();
}

b) to get to an answer: i'll often create an inner class (temporarily in some cases):

class C {
    class t_inner {
    public:
    /* ... */
        void setX(int arg) {
            /* enforce some complicated invariants... */
            this->x = arg;
        }
        const int& getX() const {
            /* ... */
            return this->x;
        }
    private:
        int x;
    };
public:
/* ... */
private:
/* ... */
    void m() {
        this->inner().setX(5);
    }
private:
    t_inner d_inner;
};
娜些时光,永不杰束 2024-12-08 05:37:53

明确的答案是。没有语言功能可以做到这一点;您可以做一些变化来实现它,但这会使您的代码变得混乱。

The clean answer is No. There is no language feature for that; you can do some variation to achieve it, but that will clutter your code.

不打扰别人 2024-12-08 05:37:53

在 Visual C++ 中,可以使用 __declspec( property ) 来实现此功能:

__declspec(property(put=setFunction, get=getFunction)) data-type property-name; 

请参阅此 文章

In Visual C++, __declspec( property ) can be used to have this feature:

__declspec(property(put=setFunction, get=getFunction)) data-type property-name; 

See this article

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文