“m_”变量前缀是什么意思?

我经常在教程、示例和其他主要与游戏开发相关的代码中看到m_前缀用于变量 (m_Worldm_Sprites,…)

为什么人们要给变量加上前缀m_ ?

145529 次浏览

这是定义成员变量的典型编程实践。因此,当您以后使用它们时,不需要看到它们的定义位置就可以知道它们的作用域。如果你已经知道作用域,并且你正在使用类似智能感知的东西,这也很好,你可以从m_开始,然后显示所有成员变量的列表。匈牙利符号的一部分,请参见例子中关于范围的部分。

m_前缀通常用于成员变量——我认为它的主要优点是有助于在公共属性和支持它的私有成员变量之间建立清晰的区分:

int m_something


public int Something => this.m_something;

对备份变量有一个一致的命名约定会有所帮助,m_前缀是做到这一点的一种方式——在不区分大小写的语言中有效。

这有多有用取决于你所使用的语言和工具。具有强大的重构工具和智能感知功能的现代ide不太需要这样的约定,而且这当然不是做到这一点的唯一方法,但在任何情况下都值得注意这种实践。

干净的代码:敏捷软件工艺手册中有一个明确的反对使用此前缀的建议:

你也不再需要给成员变量加上m_前缀。你的类和函数应该足够小,以至于你不需要它们。

这里还有一个例子(c#代码):

坏的做法:

public class Part
{
private String m_dsc; // The textual description


void SetName(string name)
{
m_dsc = name;
}
}

良好实践:

public class Part
{
private String description;


void SetDescription(string description)
{
this.description = description;
}
}

在显式歧义(即。description成员和description参数)的情况下,我们使用语言构造来引用成员变量:this

这在c++中是很常见的做法。这是因为在c++中,成员函数和成员变量的名称不能相同,而getter函数的名称通常没有“get”前缀。

class Person
{
public:
std::string name() const;


private:
std::string name; // This would lead to a compilation error.
std::string m_name; // OK.
};

main.cpp:9:19: error: duplicate member 'name'
std::string name;
^
main.cpp:6:19: note: previous declaration is here
std::string name() const;
^
1 error generated.

http://coliru.stacked-crooked.com/a/f38e7dbb047687ad

“m_”表示成员。前缀“_”也很常见。

你不应该在通过使用不同的约定/语法来解决这个问题的编程语言中使用它。

正如在其他答案中所述,m_前缀用于表示变量是类成员。这与匈牙利符号不同,因为它没有指出变量的类型,而是它的上下文。

我在c++中使用m_,但在其他一些必须使用'this'或'self'的语言中没有使用。我不喜欢看到'this->'与c++一起使用,因为它会使代码混乱。

另一个答案说m_dsc是“坏做法”,“description;”是“好做法”,但这是一个转移注意力的问题,因为这里的问题是缩写。

另一个答案是,输入this会弹出智能提示,但任何好的IDE都会有一个热键来弹出当前类成员的智能提示。

正如在许多其他响应中所述,m_是一个表示成员变量的前缀。它在c++世界中被广泛使用,并传播到其他语言中,包括Java。

在现代IDE中,这完全是多余的,因为语法高亮显示可以清楚地显示哪些变量是当地的,哪些变量是成员。然而,当语法高亮显示在90年代末出现时,这个约定已经存在了很多年,并且被牢固地设定了(至少在c++世界中是这样)。

我不知道你指的是哪个教程,但我猜他们使用惯例是由于以下两个因素之一:

  • 它们是c++教程,由习惯m_约定的人编写,和/或…
  • 他们用纯(等宽)文本编写代码,没有语法高亮显示,因此m_约定有助于使示例更清晰。
为了完成当前的答案,因为问题不是特定于语言的,一些c项目使用前缀m_来定义特定于文件的全局变量,而g_用于作用域大于所定义的文件的全局变量 在这种情况下,前缀m_定义的全局变量应该定义为static.

有关使用此约定的项目示例,请参见EDK2 (UEFI开源实现)编码约定

我还没有看到的一个论点是,像m_这样的前缀可以用来防止与__abc1d宏的名称冲突。

Regex搜索#define [a-z][A-Za-z0-9_]*[^(]/usr/include/term.h从curses/ncurses。

洛克希德·马丁公司使用了一个3前缀命名方案,这是非常棒的工作,特别是在阅读别人的代码时。

   Scope          Reference Type(*Case-by-Case)   Type


member   m     pointer p                       integer n
argument a     reference r                     short   n
local    l                                     float   f
double  f
boolean b

所以…

int A::methodCall(float af_Argument1, int* apn_Arg2)
{
lpn_Temp = apn_Arg2;
mpf_Oops = lpn_Temp;  // Here I can see I made a mistake, I should not assign an int* to a float*
}

为了它的价值而接受它。

还有人提到它的意思是一个阶级成员。Qt是一个流行的c++框架,它使用了这个符号,所以很多c++ GUI教程都使用m_。你可以看到他们几乎所有的例子都使用m_作为类成员。就我个人而言,我使用m_,因为它比this->短,感觉紧凑。