Murilo :P

C++, Computação, Programação, Web e afins :)

Como implementar facilmente getters e setters em C++

with 7 comments

Se você é como eu que odeia ficar digitando dois métodos para cada atributo que você cria em sua classe, seus problemas acabaram.
Trata-se de uma macro feita através de um #define mesmo que facilita muito a vida dos programadores OO em C++.
Vejamos a macro:

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


E eis a maneira de usar:

#include < iostream >
using namespace std;

class Teste
{
        declare(int, x); //declarando um atributo x do tipo int e seu método get e set
        declare(int, y); //declarando um atributo y do tipo int e seu método get e set
};

int main()
{
        Teste t;

        t.setx(2);
        t.sety(3);

        cout << " "<< t.gety() << endl;
}
&#91;/code&#93;
<h3>Como isso funciona?</h3>
É simples, na linha 2 da macro declaramos uma variável de acesso <strong>private</strong>
com tipo <strong>type</strong> e nome <strong>_name</strong>. Ou seja, ao chamarmos declare(int, x), será criado um atributo private int _x;. Nas linhas a seguir declaramos os métodos de acesso void setname(const type var) e type getname() que, no caso do nosso exemplo declare(int, x), se transformará em:


void setx(const int& var)
{
        _x = var;
}

int getx()
{
        return _x;
}

Eis o código final da classe Teste:

class Teste
{
        private: int _x;
        public:
        void setx(const int& var)
        {
                _x = var;
        }

        int getx()
        {
                return _x;
        }
        
        private: int _y;
        public:
        void sety(const int& var)
        {
                _y = var;
        }

        int gety()
        {
                return _y;
        }
};

Lembrando que vale para qualquer tipo. Assim podemos declarar por exemplo declare(std::string, nome)!
É isso aí... Até a próxima!


Só para esclarecer, conversando com alguns membros da comunidade C e C++ Brasil do Orkut, o membro Paulo lembrou de colocar o parâmetro passado para o setter como referência para evitar overhead e que esse tipo de declaração não funciona com qualquer tipo de dado no C++.
Comentário completo:

"Na sua macro para getters e setters, eu faria o setter receber uma referência constante (const type &valor), o que pode ser útil para não entupir a pilha quando o tipo type for um tipo não-nativo, como algo baseado em std::vector.

Por outro lado, este é um tipo de macro que alguns consideram perigoso, pois reinventa a sintaxe. Note como a declaração fica disfarçada de chamada de função, podendo induzir as pessoas a um tipo de "oba! vou usar isso fora de classes também".

Tem ainda outro problema: não funciona com qualquer tipo -- arrays, por exemplo, dariam erro."

Advertisements

Written by Murilo Adriano

21 de May de 2009 at 13:27

Posted in C/C++, Programação

Tagged with ,

7 Responses

Subscribe to comments with RSS.

  1. Queri saber o porquê das “\” e das “##”. Tem como explicar?

    Andre Brito

    21 de May de 2009 at 13:50

    • Claro Andre!!!
      As “\” são escapes de linha. Servme para poder escrever o #define em várias linhas como se fosse em uma só.
      As “##” servem para concatenar. como em set##name, se fosse setname, o pré-processador não substituiria o name. Com os ##, ele escreve o set e concatena com o valor de name.

      Um abraço!

      Murilo Adriano

      21 de May de 2009 at 16:13

  2. Hmm… interessante isso ein! Se soubesse disso uns anos atrás, teria em poupado muito trabalho nos códigos de ED e similares ><"

    Eduardo

    21 de May de 2009 at 17:17

    • Pena que se usarmos essas artimanhas em ED, o professor logo vai encrespar! hehehe 🙂

      Murilo Adriano

      21 de May de 2009 at 21:24

  3. Murilo,
    Valeu pela explicação cara. Animal isso.
    Abraço.

    Andre Brito

    21 de May de 2009 at 23:29

  4. basicamente, como criar getters e setters INÚTEIS em C++…

    O propósito de se criar esses métodos é justamente a possibilidade de se modificar a forma como se obtem um valor na interface da classe… declarar desse jeito não te dá nenhuma vantagem sobre acessar diretamente o valor do atributo, e ainda adiciona o overhead da chamada de método.

    Bad.

    Edric Garran

    5 de December de 2011 at 13:53

    • Olá Edric,

      bom, não acho que seja totalmente inútil pois o intuito do post foi mostrar como evitar reescrever coisas repetitivas, nesse caso getters e setters padrões.
      Concordo com você que pode ser feito basicamente expondo as variáveis-membro da classe para que possam ser acessadas diretamente. Porém declará-las como privadas nos dá a vantagem de poder alterar o modo em que modificamos essas variáveis com o menor esforço possível (alterando apenas a função-membro get/set apropriadamente) e não em cada lugar onde uma atribuição é feita. Então há uma utilidade visando uma maior manutenibilidade de código.

      Outra coisa que gostaria que notasse é que não é verdade que exista overhead de chamada de função-membro. Isso porque funções-membro declaradas e definidas dentro do corpo da classe são automaticamente inlined [1].

      Not so bad!
      Abraço.

      [1] http://www.parashift.com/c++-faq-lite/inline-functions.html#faq-9.8

      Murilo Adriano

      5 de December de 2011 at 14:15


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: