6

我正在将一个结构转换为一个类,这样我就可以为我的变量强制执行一个 setter 接口。
不过,我不想更改读取变量的所有实例。所以我转换了这个:

struct foo_t {
    int x;
    float y;
};

对此:

class foo_t {
    int _x;
    float _y;
public:
    foot_t() : x(_x), y(_y) {  set(0, 0.0);  }

    const int &x;
    const float &y;

    set(int x, float y)  {  _x = x;  _y = y;  }
};

我对此感兴趣,因为它似乎模仿了 C# 的公共只读属性的想法。
编译很好,我还没有看到任何问题。

除了在构造函数中关联 const 引用的样板之外,这种方法的缺点是什么?
有什么奇怪的混叠问题吗?
为什么我以前没见过这个成语?

4

4 回答 4

11

一个问题是您的类不再是可复制或可分配的,因此不能存储在像向量这样的 C++ 容器中。另一个是维护您的代码的经验丰富的 C++ 程序员会看到它并惊呼“WTF!!” 非常响亮,这绝不是一件好事。

于 2010-06-01T19:46:29.780 回答
5

存在一个别名问题,因为您公开了对foo_t的内部数据的引用,因此对象外部的代码可能会foo_t在对象的生命周期之外保留对其数据的引用。考虑:

foo_t* f = new foo_t();
const int& x2 = f->x;
delete f;
std::cout << x2; // Undefined behavior; x2 refers into a foo_t object that was deleted

或者,更简单:

const int& x2 = foo_t().x;
std::cout << x2; // Undefined behvior; x2 refers into a foo_t object that no longer exists

这些并不是特别现实的例子,但是当对象公开或返回对其数据(公共或私有)的引用时,这是一个潜在的问题。当然,在对象的生命周期之后保持对foo_t对象本身的引用也是可能的,但这可能更难错过或意外发生。

并不是说这是反对您正在做的事情的论据。事实上,我以前使用过这种模式(出于不同的原因),我认为它没有任何本质上的错误,除了你似乎认识到的缺乏封装。上述问题只是需要注意的事情。

于 2010-06-01T19:44:58.513 回答
2

你也可以做这样的事情,它适用于内置类型:(对不起,如果这个代码片段包含错误,但你明白了)

template <typename T, typename F>
class read_only{
   typedef read_only<T, F> my_type;
   friend F;

public:
   operator T() const {return mVal;}

private:
   my_type operator=(const T& val) {mVal = val; return *this;}
   T mVal;
};


class MyClass {
public:
   read_only <int, MyClass> mInt;
   void MyFunc() {
      mInt = 7; //Works
   }
};

AnyFunction(){
   MyClass myClass;
   int x = myClass.mVal; // Works (okay it hasnt been initalized yet so you might get a warning =)
   myClass.mVal = 7; // Error
}
于 2010-06-01T20:01:14.630 回答
0

你的方法不灵活。当您对每个变量都有一个时,这意味着如果您在类中添加一些东西,您getter / setter不必重写您的方法。set

这不好,因为你不能拥有constnon-const吸气剂(很少使用,但有时可能很有用)。

您不能复制引用,因此,您的类变得不可复制。

此外,在您的类中初始化引用意味着额外的内存,如果我们正在谈论,例如,顶点类(尽管我认为它实际上不应该是一个类),这可能会成为一场灾难。


[以下内容完全是主观的]

在我看来,getter 和 setter 的目的不是简单的修改,而是封装一系列导致值修改或返回值(我们将其视为可见结果)的动作。

在您的示例的情况下,个人 struct 会更有效,因为它包装 POD 数据并在逻辑上“结构化”它。

于 2010-06-01T19:44:51.013 回答