我正在使用下划线命名样式(与camel case相反)编写C ++,这也是STL和boost使用的。但是,由于类型和变量/函数都被命名为全小写,因此如下的成员变量声明将导致编译器错误(或至少是麻烦):
position position;
名为 position 的成员变量,其类型为 position 。我不知道如何命名它:它通常是一个位置,但它也是对象的位置。在驼峰的情况下,编译器可以这样做:
Position position;
但在C ++中它会导致问题。我不想切换到驼峰情况,使用匈牙利表示法或添加尾随下划线因此,所以我想知道:将类型的成员命名为类型是否是一个好习惯?
在C中,使用神秘的单字母变量是非常常见的:
int i;
但我发现有点,嗯,神秘:
position p;
我可以使用变量命名的经验法则来避免这种情况吗?
如果您需要处理某些内容,我的代码中会有更多示例:
mouse_over(entity entity) // Returns true if the mouse is over the entity
manager &manager; // A reference to the framework's manager
audio audio; // The audio subsystem
修改
我很想知道Bjarne Stroustrup本人在这个问题上是否有话要说。显然,他没有,但他建议编码约定可以解决我的编译器问题:
例如,大写非标准库用户定义类型并使用小写字母开始非类型
这与STL和提升是一致的,所以我可能会使用它。但是,大多数人都同意,无论是否编译,都应避免使用此命名。 Stroustrup也是如此:
选择仅以大小写不同的名称是不明智的。
答案 0 :(得分:10)
本地意义很少是该类型的唯一全局描述:
cartesian_point_2d position; // rectangular, not polar coordinates
mouse_over(ui_entity entity); // not a business layer entity
xyz_manager& manager; // what's a manager without something to manage?
audio_system audio;
答案 1 :(得分:8)
赋予变量与其类型相同的名称几乎总是一个坏主意,因为它很难分辨哪些代码引用了类型以及哪些代码引用了变量。例如,请考虑以下类:
struct position
{
void operator()() { }
};
// later on, somewhere:
position position;
现在,如果我们看到一行代码使用:
position()
我们无法判断是构造position
对象还是调用position::operator()()
。我们必须返回并查看当前是否存在名为position
的对象。
命名约定是一个非常敏感,主观和争论的事情。我建议选择一种以某种方式区分类型和变量的方法。就个人而言,我选择将我的类型大写,并将我的变量保留为以小写字母开头。
如何区分它们(您使用大小写或尾随下划线的建议都很常见),只要您的使用是一致的。
答案 2 :(得分:3)
在类型之后命名变量确实是一种不好的做法。代码应该尽可能与类型无关。这意味着对实际类型的任何引用都应限于声明(同样,尽可能多)。试图将类型信息嵌入变量名称将违反该原则。不要这样做。
人们可能想要嵌入到变量名中的是变量的语义含义。如“width”,“length”,“index”,“coordinate”,“rectangle”,“color”,“string”,“converter”等。不幸的是,许多人在看到它时错误地认为名称的这些部分旨在描述变量的类型。这种误解常常使他们在代码中稍后参与这种不良实践(在其类型之后命名变量)。
这种误解的经典着名例子是所谓的匈牙利符号。匈牙利表示法意味着在变量名称前加上特殊的统一前缀,用于描述变量的语义。在这种原始形式中,匈牙利符号是一种非常有用的良好命名惯例。但是,在许多实际情况中,它会被扭曲成完全不同的东西:在变量名前加上描述其类型的内容。后者当然不是一个好主意。
答案 3 :(得分:2)
是的,这是一种不好的做法。变量名称如果具有较长的生命周期或重要意义(临时性可以),则应该更具体。请记住,C ++是非常严格的类型 - 你不能拥有变量,也不能确定它的类型是什么。例如,变量Type类型基本上只意味着它没有名称。
答案 4 :(得分:2)
就个人而言,我将我的班级名称大写。
我不同意,“在这种特定情况下,选择仅按大写字母区分的名称是不明智的”。选择容易混淆的名字是不明智的。 PoSItIoN
和PoSiTIoN
混淆相似。 Position
和position
不是。只需确保在搜索代码时,您知道并且可以控制您是否区分大小写或不敏感。
如果我的函数只使用一个特定类型的变量,那么我可能会在类型之后命名,因为在英语中,如果有的话,“我们所讨论的唯一位置”,我们' d将其称为“位置”。因此,变量名称可以合理地为position
。
如果做错了,在你的例子中我可能会选择:
position pos; // pretty sure people will realise I don't mean "positron".
mouse_over(entity target) // Returns true if the mouse is over the entity
manager &fmanager; // A reference to the framework's manager
devices::audio audio; // The audio subsystem
audio self; // "this" audio subsystem
audio audio_out; // The audio subsystem I'm configured to use for output
最后一个例子应该表明命名空间可以解决这些问题 - 在定义audio
的命名空间之外,您可以安全地将其称为audio
。在该命名空间内,在音频子系统上运行的函数经常是audio
类接口的一部分,它恰好是自由函数(在这种情况下使用self
,other
,{等惯例{1}},lhs
),或者是某种分层设备或系统,它将音频子系统作为依赖项(在这种情况下,依赖于什么目的?)。
rhs
和entity
是类的可怕名称,因为它们都没有告诉你关于类代表什么的任何信息。每一个离散的东西都是一个“实体”,虽然并非所有东西都管理其他东西,但“管理”却毫无希望地模糊。
答案 5 :(得分:1)
这就是为什么我选择使用m_为成员变量添加前缀的旧MFC实践,如“m_position”。很多Java人会因为基本相同的原因而做“thePosition”,不过如果你指出他们变成有趣的颜色并对你咆哮时的相似性。
答案 6 :(得分:1)
我经常遇到同样的“问题”。我认为这是一个abstration的问题:在Position的情况下,我建议抽象一点,并引入一个类型Point或类似的东西。或者指定什么位置:
position mouse_pointer_pos;
答案 7 :(得分:0)
您可以遵循现有的指南,例如Google's C++ style guide
很高兴知道命名是一个重要的问题,但根据我的经验 过多地思考它是有害的,因为没有意识到它。
我已经尝试过匈牙利语并且不喜欢它,大多数优秀的程序员我 知道不要用它。
我要说的是它使代码的可读性降低。
答案 8 :(得分:0)
不,我有时会这样做,它不会在Microsoft世界中引起问题。例如,
class compiler
{
symbol_table symbol_table;
};
从未引起任何混乱。顺便说一句,我称我的猫为“猫”,那也没有引起混乱。
答案 9 :(得分:0)
此命名约定imo的最大问题是,程序员不清楚表达式是引用类型还是对象。消除这种歧义的一种方法是,将代码包装在名称空间中(应如此),并使用明确的限定条件,甚至在内部使用时也是如此:
namespace my_ns {
struct audio { ... };
struct string { ... };
// Internal function whose logic doesn't require explicit qualifications.
void do_something()
{
// Use explicit qualification nevertheless.
my_ns::audio audio;
audio.play("impenetrable.sd2"); // okay
my_ns::string string;
string.size(); // okay
// string{}.size(); // oof, tryna re-instantiate object? compilation error
my_ns::string{}.size(); // okay, size of just created temporary string
}
}
这很像您使用标准类型(例如std::string
)的方式。由于所有用户定义的类型都将使用其名称空间进行限定,因此类型和对象之间不会存在歧义。当然,这样做的缺点是冗长:
namespace my_ns {
struct audio {
// Using explicit qualification; pretty verbose.
void play(my_ns::string a1, my_ns::string a2, my_ns::string a3);
// Without explicit qualification; saves 21 characters.
void play(string a1, string a2, string a3);
};
}
答案 10 :(得分:-1)
简短和半错误答案:如果你有足够的变量在一个地方使用,你需要非神秘的变量名,那么你可能有太多的变量。
虽然我在某种程度上实际上不同意这一点。我认为这有一定道理,但仅限于此。
C ++中的一些简短变量名称只是传统的,人们知道它们的含义,因为它们已经用C / C ++编程了一段时间。使用i
作为索引变量就是一个例子。
我认为应该根据其目的命名变量名称。这个位置的立场是什么?经理在管理什么?为什么音频子系统的这个特定实例需要存在?
尾随_
表示法用于区分成员变量名称。当有人开始提到x
无处可见x_
并知道它来自类时,并且未在封闭范围或全局范围内声明时,它会非常有用。