用C ++编程,我经常想给一个类的用户一个属性的只读访问权限,而这个类本身就是读写访问权限。我讨厌XxxGet()
方法,因此我经常使用public const &
私有属性,如下所示:
class counter {
private:
int _count;
public:
const int & count;
counter : _count( 0 ), count( _count ){}
void inc( void ){ _counter++; }
};
这个技巧有一个共同的名字吗?
答案 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
引用引用与int
中count
引用相同的c1
指的是,这可能导致代码中难以发现的细微问题实际上很难调试。
答案 1 :(得分:15)
修改强>
刚刚我想到了一个可以被视为相同模式的名称。虽然通常不用于成员变量。
实际上可能有一个名称,正如Boost Tuple库以及TR1 / C ++ 11实现所普及的那样:
典型示例:
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