O que significa o prefixo da variável `m_`?

154

Muitas vezes vejo m_prefixo usado para variáveis ( m_World, m_Sprites...) em tutoriais, exemplos e outros códigos, principalmente relacionadas com o desenvolvimento do jogo.

Por que as pessoas adicionam prefixo m_às variáveis?

kravemir
fonte
18
Antes de seguir o exemplo da notação húngara, faça um exame de histórico sobre o que realmente é a notação húngara. Porque nomear um int iCounter é inútil. Mas nomear um int xAnnotationPos e yAnnotationPos é razoável. Use a versão semântica.
AkselK
Às vezes, os módulos importados prefixam funções e variáveis ​​para que você tenha menos probabilidade de substituí-las por seu próprio código. É uma maneira de 'reservar' nomes para um uso específico.
usar o seguinte código
3
Embora a notação "húngara" seja frequentemente ridicularizada, o sabor particular que denota escopo variável tem algumas vantagens reais. Além de identificar o escopo da variável, evita colisões de nomes, como quando um local, um parm e um membro têm a mesma intenção e, portanto, o mesmo nome "semântico". Isso pode tornar a manutenção de grandes bases de código mais simples e menos sujeitas a erros.
Hot Licks
8
Existem argumentos a favor e contra qualquer padrão de codificação, mas a pergunta pergunta claramente o que é a m_favor, mas metade das respostas aqui são um comentário sobre por que todos acham que seu favorito atual é o melhor.
cz

Respostas:

108

Essa é uma prática típica de programação para definir variáveis ​​que são variáveis ​​membros. Portanto, quando você os usar mais tarde, não precisará ver onde eles estão definidos para conhecer seu escopo. Isso também é ótimo se você já conhece o escopo e está usando algo como o intelliSense , pode começar m_e uma lista de todas as suas variáveis ​​de membro é mostrada. Parte da notação húngara, veja a parte sobre escopo nos exemplos aqui .

MichaelHouse
fonte
51
Pior argumento para uma convenção de nomenclatura de todos os tempos, basta pressionar ctrl + space para o intellisense.
orlp
11
@nightcracker eventhough Eu não gosto do prefixo, ele quer dizer que quando você digita m_ e depois "CTRL + ESPAÇO" (a menos que seja automático), você obtém uma lista contendo apenas seus membros. Não é exatamente uma boa razão, mas é uma vantagem.
Sidar
13
Vale ressaltar que existem muitas outras maneiras mais ou menos padrão de fazer a mesma coisa; "m_variable", "m_Variable", "mVariable", "_variable", "_Variable" ... qual o caminho que é 'melhor' ou 'certo' (ou se é necessário fazê-lo) é um argumento tão contencioso e infrutífero quanto ' espaços versus tabulações ". :)
Trevor Powell
49
Eu prefiro apenas usar "this->" - meio que torna "m_" redundante e é ainda melhor, pois é imposta pelo compilador (em teoria, você pode exibir "m_" em qualquer tipo de variável; não pode fazer isso com "this-> "). Parte de mim deseja que o C ++ seja padronizado ao tornar "this->" obrigatório. Mas isso está entrando mais no mundo da discussão do que sendo uma resposta.
3
@LaurentCouvidou, você não pode realmente impor que os desenvolvedores criem variáveis ​​de membro com o prefixo de m_qualquer um.
SomeWritesReserved
94

No Código Limpo: Um Manual do Artesanato em Software Ágil, há uma recomendação explícita contra o uso desse prefixo:

Você também não precisa prefixar variáveis ​​de membro com m_mais. Suas classes e funções devem ser pequenas o suficiente para que você não precise delas.

Há também um exemplo (código C #) disso:

Má prática:

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

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

Boa prática:

public class Part
{
    private String description;

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

Contamos com construções de linguagem para se referir a variáveis de membro, no caso de explicitamente ambigüidade ( ie , descriptionmembro e descriptionparâmetro): this.

InfZero
fonte
6
O texto poderia ser "há uma recomendação explícita CONTRA o uso desse prefixo:"
Xofo 6/17/17
Eu sou alguém tão feliz escreveu
dmitreyg
Outro motivo é que no java getter / setter é assumido como getName / setName, portanto, getM_name é ruim e você precisa manipulá-los um por um.
Leon
Obrigado por escrever isso. Eu só queria salientar que o livro que você citou está publicado desde agosto de 2008 - e ainda encontro essa má prática no novo código hoje (2019).
Alexlomba87 12/08/19
20

É prática comum em C ++. Isso ocorre porque em C ++ você não pode ter o mesmo nome para a função e a variável membro, e as funções getter geralmente são nomeadas sem o prefixo "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

estados "m_" para o "membro". O prefixo "_" também é comum.

Você não deve usá-lo em linguagens de programação que resolvem esse problema usando diferentes convenções / gramática.

doc
fonte
11

O m_prefixo é frequentemente usado para variáveis ​​de membro - acho que sua principal vantagem é que ele ajuda a criar uma distinção clara entre uma propriedade pública e a variável de membro privado que a apoia:

int m_something

public int Something => this.m_something; 

Pode ajudar a ter uma convenção de nomenclatura consistente para o backup de variáveis, e o m_prefixo é uma maneira de fazer isso - que funciona em linguagens que não diferenciam maiúsculas de minúsculas.

A utilidade disso depende dos idiomas e das ferramentas que você está usando. Os IDEs modernos, com fortes ferramentas de refator e inteligência intelectual, têm menos necessidade de convenções como essa, e certamente não é a única maneira de fazer isso, mas vale a pena estar ciente da prática em qualquer caso.

Keith
fonte
5
Se você precisa escrever this.no seu idioma, m_é realmente inútil.
Ruslan
@Ruslan the m_é distingui-lo da propriedade que ele faz - assim, this.Somethingpara a propriedade vs this.m_somethingpara o membro de apoio. Não é uma convenção que prefiro a mim mesma, mas já a vi usada em linguagens insensíveis a casos (como o VB).
21418 Keith
1
Por que não, this.Somethingpela propriedade e this.somethingpelo apoio? Ou this._somethingpelo apoio? this.m_somethingé redundante. Eu uso _somethingpara que eu não acidentalmente digitá-lo quando eu vou para digitar Something, nada a ver com membershipness ou não
AustinWBryan
@AustinWBryan veja meu comentário anterior sobre idiomas que não diferenciam maiúsculas de minúsculas. Sim, um _prefixo por si só faria o trabalho, mas m_é a convenção. Não é um que eu usaria pessoalmente, mas se você o vir no código, essa foi a intenção do autor.
Keith
7

Conforme indicado nas outras respostas, o m_prefixo é usado para indicar que uma variável é um membro da classe. Isso é diferente da notação húngara porque não indica o tipo da variável, mas seu contexto.

Uso m_em C ++, mas não em outras linguagens em que 'this' ou 'self' é obrigatório. Eu não gosto de ver 'this->' usado com C ++ porque desorganiza o código.

Outra resposta diz que m_dscé "má prática" e 'descrição;' é "boa prática", mas esse é um problema, porque o problema é a abreviação.

Outra resposta diz que a digitação thisexibe o IntelliSense, mas qualquer IDE bom terá uma tecla de atalho para exibir o IntelliSense para os membros da classe atual.

Quentin 2
fonte
"mas este é um arenque vermelho" - Bom ponto. Uma comparação justa seria m_descriptionvs description.
Batalha
3

Como afirmado em muitas outras respostas, m_ é um prefixo que indica variáveis ​​de membros. É / foi comumente usado no mundo C ++ e propagado para outras linguagens também, incluindo Java.

Em um IDE moderno, é completamente redundante, pois o destaque da sintaxe torna evidente quais variáveis ​​são locais e quais são membros . No entanto, quando o destaque da sintaxe apareceu no final dos anos 90, a convenção já existia há muitos anos e estava firmemente definida (pelo menos no mundo C ++).

Não sei a quais tutoriais você está se referindo, mas acho que eles estão usando a convenção devido a um dos dois fatores:

  • São tutoriais em C ++, escritos por pessoas acostumadas à convenção m_ e / ou ...
  • Eles escrevem código em texto simples (monoespaçado), sem realce de sintaxe, portanto a convenção m_ é útil para tornar os exemplos mais claros.
sergut
fonte
Um exemplo pode ser este: wiki.qt.io/How_to_Use_QSettings Como o Qt Creator está usando o destaque, a primeira suposição pode aparecer. Um pouco diferente pode ser outra convenção usando _object () para objetos particulares de uma classe e p_variable se for um ponteiro, pois os dois não são tão altos quanto eu conheço e parecem fazer sentido usá-lo.
Ivanovic
3

A Lockheed Martin usa um esquema de nomeação de três prefixos, que foi maravilhoso de se trabalhar, especialmente ao ler o código de outras pessoas.

   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

Assim...

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*
}

Leve para o que vale a pena.

jiveturkey
fonte
Impressionante. Obrigado pelo "exemplo". É realmente útil quando você está editando 200.000 linhas de código.
jiveturkey 18/02
1
Não há necessidade de se defender. Sinceramente, estou tentando ajudá-lo, mostrando que há um erro na sua resposta. Deixe-me ser mais claro, então: Não importa se você tem 5 ou 200000 linhas de código: O compilador não permitirá que você faça uma atribuição com tipos de ponteiros incompatíveis. Portanto, o argumento apresentado no comentário é discutível.
Cássio Renan
Não quis parecer defensivo. Desculpe.
jiveturkey 19/02
É uma variação da notação húngara, que não faz sentido nas línguas modernas ...
doc
2

Para concluir as respostas atuais e como a pergunta não é específica ao idioma, alguns projetos C usam o prefixo m_para definir variáveis ​​globais específicas de um arquivo - e g_para variáveis ​​globais com escopo maior que o arquivo definido.
Nesse caso, variáveis ​​globais definidas com prefixo m_ devem ser definidas como static.

Consulte a convenção de codificação EDK2 (uma implementação de código aberto UEFI) para obter um exemplo de projeto usando essa convenção.

OlivierM
fonte
1

Um argumento que ainda não vi é que um prefixo como m_pode ser usado para impedir o conflito de nomes com #defineas macro.

Pesquisa #define [a-z][A-Za-z0-9_]*[^(]em Regex por /usr/include/term.hcurses / ncurses.

yyny
fonte