在C ++类中使用const引用字段作为只读getter是不是很好?
我的意思是,这段代码是否符合良好做法?
class check{
private:
int _x;
public:
const int& x = _x;
void setX(int v){
_x = v;
}
};
它非常像C#属性,恕我直言,并且在类使用代码中非常简单和干净:
check s;
int i;
std::cin >> i;
s.setX(i);
std::cout << s.x << '\n';
s.setX(7);
// s.x = i; // Error
std::cout<<s.x<<'\n';
答案 0 :(得分:19)
这段代码是否符合良好做法?
不是真的,因为它会带来不必要的复杂性和空间开销。
此外,无论访问的值是什么,您都无法执行运行时检查和/或断言。
此外,生命周期和语义会发生什么?
尝试将代码中的一个check
分配给另一个,看看会发生什么。分配不正确,因为该类是不可分配的。您应该提供一个复制和移动构造函数来处理引用,这样它就不会引用旧对象的数据成员。
最好直接使用_x
并使用简单的内联getter函数。
答案 1 :(得分:6)
一般来说,不是是一种良好的做法。
imho,在课堂使用代码中非常简单和干净。
为什么要更清晰,更容易?
“经典”方法听起来更清晰,例如:
class Foo {
public:
void set_num(int value) noexcept { m_num = value; }
int get_num() const noexcept { return m_num; }
void set_string(std::string value) noexcept {
m_str = std::move(value);
}
const std::string& get_string() const noexcept {
return m_str;
}
private:
int m_num;
std::string m_str;
};
从表演的角度来看,这种方法应该是首选。
get_variable
不会引入比“参考方法”更多的开销。此外,它可以被编译器高度优化(因为代码简单)。答案 2 :(得分:4)
你提出的建议总的来说是一个坏主意:
如果您对属性的意图是使代码更简洁,则不必在函数名称中使用“get”和“set”;这是一种老式的做法。您可以使用“属性”的实际名称作为函数名称,并且可以重载getter和setter:
class Cheque {
public:
int x() const {
return x_;
}
Cheque & x(int newX) {
x_ = newX;
return *this;
}
private:
int x_;
}
// Usage:
// int amt = myCheque.x(1234);
// Cheque c = Cheque().x(123);
按照上面的代码返回*this
,您可以使用method chaining;一种实现Fluent interface习语的方法。
答案 3 :(得分:1)
当C#编译一个属性时,它会被编译成一个getter和一个setter函数。
以下是一些证明这一事实的C#代码:
using System;
namespace Reflect
{
class Program
{
class X
{
public int Prop { get; set; }
}
static void Main(string[] args)
{
var type = typeof(X);
foreach (var method in type.GetMethods())
{
Console.WriteLine(method.Name);
}
Console.ReadKey();
}
}
}
您的输出应为:
get_Prop
set_Prop
ToString
Equals
GetHashCode
GetType
get_Prop
是实现getter的函数。
set_Prop
是实现setter的函数。
所以,即使你所做的事情看起来很相似,也不一样。
坦率地说,在C ++中尝试模拟“属性语法”的几乎所有事情都会以这种或那种方式落空。大多数解决方案要么花费你的记忆,要么它会有一些限制,使它比有用的更麻烦。
只要学会与吸气者和二传手一起生活。 吸气剂和制定者是良好做法。 它们很短,很简单,很灵活,通常很适合内联,每个人都理解他们做的事情等等。