C/C++: Accessors(getters) e mutators(setters) de forma fácil usando macros

Continuando

Anteriormente, acho que até o ultimo post que eu fiz, falei sobre accessors(getters) e mutators(setters).

Isso foi a algum tempo atrás, e apesar de ser uma maneira muito elegante, ainda é uma maneira um pouco repetitiva, no sentido que você deve se preocupar e repetir algumas partes do processo. Isso é uma parte do processo que pode ser feita de forma automática, com muitas vantagens, com uma ajudinha de macros.

Estava vendo que o Murilo fez algo de forma parecida, e achei muito interessante. Resolvi copiar e alterar para o modo como eu mostrei em meu post passado, e mudei algumas coisas, como o nome de “declare” para “declare_am”, só para fica mais explicito….

Vejam agora que toda vez que eu quiser declarar uma variável data do tipo inteiro com getters e setters, é só usar declare_am(int,data)! Muito fácil.

Segue o código abaixo, usem para facilitar a vida, e qualquer discussão estamos ai :].

#include	<iostream>
#include	<cstdlib>

#define declare_am(type, name) \
private: type _##name; \
public: \
void name(const type& var){\
	_##name = var;\
}\
\
const type & name(){\
	return _##name; \
}\

class Teste_accessor_mutator{
	declare_am(int,data);
	declare_am(int,x);
	declare_am(int,y);
};

int main( int argc, char *argv[] ){
	Teste_accessor_mutator teste;

	teste.data(100);
	teste.x(1);
	teste.y(2);
	std::cout << teste.data() << std::endl ;
	std::cout << teste.x() << std::endl ;
	std::cout << teste.y() << std::endl ;
	return EXIT_SUCCESS;
} /* ---------- end of function main ---------- */

Advertisements

3 responses to “C/C++: Accessors(getters) e mutators(setters) de forma fácil usando macros

  • Vinipsmaker

    Por que colocou para retornar a variável por referência constante no acessor?

    E coloca var_ no lugar de _var, já que alguns nomes reservados começam com _.

    • psychomantys

      Então, fica referencia constante para que o que seja passado para fora da função membro o dado de forma que evite copias desnecessárias, de forma o mais direta possível.

      Como não tem move, eu tentei ao máximo não gerar copias desnecessárias, achei que essa seria a melhor opção, até para o compilador entender melhor e otimizar mais.

      Pode ter sido um exagero, mas achei que seria bom fazer assim, pelo menos não achei que ficasse pior e parece garantir bem a performance. Pelo menos não vejo um motivo para usar diferente se quiser essas garantias, pelo menos para o compilador entender melhor o que eu quero. Se tiver alguma coisa de ruim nisso ou ilógico, gostaria de saber :].

      Acho que o const no retorno é mais fácil de explicar, é porque não se deve alterar o retorno, porque é apenas para acessar e não para alterar o que ele retorna.

      Com relação ao _, acho que a ideia é que seja uma palavra reservada da classe mesmo, então por isso o _. Normalmente até as coisas reservadas tem __, e não _ apenas, então acho razoável com _. Ou para implementações você usa um espaço de nomes exclusivo para você, como pro exemplo priv ou __priv ou qq outro nome.

      Mas você também pode alterar o nome que o dado dentro da classe é armazenado, a interface ficando igual acaba fazendo com que tanto faz o como ele é representado internamente. Além de tudo fica possível fazer como você quiser nesse caso.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: