公共const和私有可写属性的名称?

时间:2011-09-15 14:12:24

标签: c++

用C ++编程,我经常想给一个类的用户一个属性的只读访问权限,而这个类本身就是读写访问权限。我讨厌XxxGet()方法,因此我经常使用public const &私有属性,如下所示:

class counter {
  private:
     int _count;

  public:
     const int & count;

     counter : _count( 0 ), count( _count ){}

     void inc( void ){ _counter++; }
};

这个技巧有一个共同的名字吗?

3 个答案:

答案 0 :(得分:24)

我的个人名称是坏主意

我会避免你所遵循的方法,因为它会产生额外的不必要的成本。如果你添加访问器,他们可以根据需要内联,只需要输入一对额外的括号:

class counter {
    int _count;
public:
    counter() : _count() {}
    int count() const { return _count; }
    void inc() { ++_count; }
};

主要区别在于,在您的解决方案中,您将对象的大小增加一个引用(对于大多数实现,这意味着指针),然后每次访问都需要额外的间接。另一方面,使用访问器,使用实际变量,函数将被优化(内联,并解析为对变量的单个读取)。

作为该类型构造的正确名称,我从未在C ++中看到过您的特定构造,但如果您考虑其他语言,那么这是C#中属性的基本概念,你可以让getter公开,setter私有。

编辑:我认为糟糕的主意可能被误解为个人观点(它是),但请考虑该设计的副作用:

由于对象中的引用,您禁止隐式定义赋值运算符。更糟糕的是,复制构造函数编译但不能按预期工作:

// consider the implementation with the const reference
counter c1;
counter c2( c1 );          // compiles, so it must work
c2.inc();
std::cout << c2.count;   // outputs 0
// c2 = c1;              // error: well, at least this does not compile!

问题是编译器生成的复制构造函数会使count中的c2引用引用与intcount引用相同的c1指的是,这可能导致代码中难以发现的细微问题实际上很难调试。

答案 1 :(得分:15)

修改

刚刚我想到了一个可以被视为相同模式的名称。虽然通常不用于成员变量。

实际上可能有一个名称,正如Boost Tuple库以及TR1 / C ++ 11实现所普及的那样:

Tieing

典型示例:

 tuple<int> tie(ref(some_var));
 // or shorter:
 auto tied = tie(var1, var2, var3);

分配并发症

这个(反?)模式的最接近的名字我可以_ 立即之前想到的是:指针或参考别名。由于许多原因,这不是一个好主意,其中一些已被提及

  • 班级布局+大小
  • 复制/分配语义
  • 编译器优化:当知道引用可能指向相同的内存位置时,编译器将避免对(寄存器分配的)变量的值进行假设。

除了David提出的观点之外,编译器将无法生成默认

  • 语义上有效的复制构造函数
  • 赋值运算符
  • 移动赋值运算符

现在包含引用的类。另请注意,您的课程不再可能是POD

答案 2 :(得分:1)

其他一些人已经谴责了这个想法,我(大多数)倾向于同意这个想法。虽然很多人可能(至少)不喜欢它,但如果我要支持这个命令,我会做这样的事情:

class counter { 
    int count_;
public:
    counter(int init=0) : count_(init) {}
    operator int() const { return count_; }
    void inc() { ++count_; }
};

这个问题的一个问题是与一般隐式转换共享的问题:即使您不希望隐式转换也会发生隐式转换。 OTOH,它是用户提供的转换实际上消除了许多问题 - 在任何给定的情况下只会自动发生一次隐式转换,所以(例如)你提供了转换为{{1}的事实} not 意味着值{0}的int可以隐式地从counter转换为counter到(null){{1}因为这将涉及两次隐式转换。

有时候这可能会导致问题,在这种情况下(从C ++ 11开始)你可以创建转换运算符int,所以它只会在/如果用户明确表示时发生转换如:

pointer to T