Problemas do polimorfismo

834 views
Skip to first unread message

Thiago Adams

unread,
Jan 27, 2013, 3:22:35 PM1/27/13
to ccppbrasil
Um assunto que me chama bastante atenção são as questões relativas ao
polimorfismo dinâmico. Ao mesmo tempo que representa uma solução ele
também representa
um problema de acoplamento e dificuldade de re-uso.

Algo ruim da OOP é o acoplamento criado pelas heranças.

A melhor forma de resolver um problema é quebrando-o em problemas
menores
independentes.
É neste ponto que a herança atrapalha, pois o problema se torna
dependente de
toda a cadeia de classes, da base para as derivadas.

A herança em C++ pode ser evitada facilmente em vários casos. Aqui
neste
grupo já foi sugerido "por que você usou herança?" justamente pois se
tratava
de um caso aonde não era necessária.
O maior motivo para se usar herança é o polimorfismo dinâmico.

A solução de implementação do polimorfismo dinâmico usada no C++ é
eficiente,
usa pouca memória e é relativamente fácil de ser implementada no
compilador.
Ela promove a "interface" que pode ter separação completa da
implementação e
isso é útil em vários cenários aonde o compilador não precisa conhecer
a implementação.
Portanto o modelo adotado tem vários pontos positivos e justamente por
isso está presente.

Apesar dos pontos positivos este modelo depende da herança que, como
dito anteriormente,
possui desvantagens. Além da herança ele depende da "interface"
definida.

Em alguns casos não seria preciso a barreira da interface e o
compilador poderia conhecer os tipos envolvidos. Mesmo assim, o
polimorfismo dinâmico
não é um detalhe de implementação e as classes precisam logicamente,
através da definição
das funções virtuais e herança, serem polimórficas e acopladas através
de interfaces.

Como minimizar os problemas da herança e polimorfismo?
Quais as alternativas para polimorfismo dinâmico?
O que poderia ser alterado na linguagem?

Ivan lopes

unread,
Jan 27, 2013, 6:20:56 PM1/27/13
to ccppb...@googlegroups.com
o uso de Design Patterns "gof" é uma resposta a sua pergunta ou estou falando besteira???


2013/1/27 Thiago Adams <thiago...@gmail.com>
--
--
Antes de enviar um e-mail para o grupo leia:
                     http://www.ccppbrasil.org/wiki/Lista:AntesdePerguntar
--~--~---------~--~----~---------------------------------~----------~--~----~
[&] Colabore com a Pesquisa de Preferência de Conteúdo
              para Eventos do Grupo C & C++ Brasil:
                        http://www.surveymonkey.com/s/GBBGTXN
------~----~-------~---~---~---~---~----------------~------------~---------~
[&] C & C++ Brasil - http://www.ccppbrasil.org/
Para sair dessa lista, envie um e-mail para ccppbrasil-...@googlegroups.com
Para mais opções, visite http://groups.google.com/group/ccppbrasil
--~--~---------~--~----~--~-~--~---~----~-----------------~--~----------~
Emprego & carreira:  vag...@ccppbrasil.org
http://groups.google.com/group/dev-guys?hl=en




Walter Mascarenhas

unread,
Jan 28, 2013, 5:37:29 AM1/28/13
to ccppb...@googlegroups.com

  lopesi:

     Design patterns só dão uma visão genérica de como um problema
poderia ser resolvido. Creio que eles não ajudam a responder
a questão do Thiago, porque mesmo após encontrar o design pattern
apropriado ao seu problema você precisará implementá-lo e ai
terá que decidir se usa polimorfismo dinâmico ou estático, por
exemplo.

  Thiago,

    Sou cada vez mais discrente em polimorfismo dinâmico. Em C++,
polimorfismo estático, via programação genérica com templates, é uma alternativa
bem melhor na maioria dos casos. Infelizmente esta última alternativa
é bem menos popular que o polimorfismo dinâmico. As pessoas realmente
tem mais dificuldade para entender código parametrizado.
Além disso, a formação com ênfase em Java e C# é o padrão nas
escolas, mas seus generics são muito menos poderosos que os
templates em C++. Com isto as pessoas não aprendem a apreciar o
poder da programação genérica, simplesmente porque a linguagem
que usam não permite o seu uso pleno.
 
   Quanto a mudanças na linguagem, acredito que o que
está no standard do C++11 já é suficiente para muitos usos. Antes
de acrescentar coisas novas seria bom aprender bem as que já
existem. Esta semana por exemplo me caiu a ficha de como
template aliases podem ser úteis. Só por causa deste detalhe
não usarei Visual C++ por um bom tempo (tive que usar até
sábado por razões comerciais)

   Resumindo, o que está disponível hoje em C++11, em compiladores
como gcc 4.7 e CLang 3.1 já oferece boas alternativas ao polimorfismo
dinâmico. Na minha opinião falta explorarmos mais as implicações
do que existe hoje e depois partir para propor novas features para
o C++21.

Thiago Adams

unread,
Jan 28, 2013, 6:33:09 AM1/28/13
to ccppbrasil


On Jan 27, 9:20 pm, Ivan lopes <lopesivan....@gmail.com> wrote:
> o uso de *Design Patterns "gof" *é uma resposta a sua pergunta ou estou
> falando besteira???

Quem gosta de OOP, como no caso GoF, diria que é
preciso fazer interfaces mínimas e bem definidas.
No mundo ideal deles, se faria um diagrama UML com
todas as heranças e definição de interfaces. Para
um software grande isso cria um quebra cabeça
de dependências e acoplamentos.

Thiago Adams

unread,
Jan 28, 2013, 6:38:46 AM1/28/13
to ccppbrasil

O problema só existe no polimorfismo dinâmico, pois o polimorfismo
estático não necessita herança.

P.

unread,
Jan 28, 2013, 8:39:27 AM1/28/13
to ccppb...@googlegroups.com
Em domingo, 27 de janeiro de 2013 18h22min35s UTC-2, Thiago Adams escreveu:
Um assunto que me chama bastante atenção são as questões relativas ao
polimorfismo dinâmico. Ao mesmo tempo que representa uma solução ele
também representa
um problema de acoplamento e dificuldade de re-uso.

Algo ruim da OOP é o acoplamento criado pelas heranças.


Algo ruim em que sentido? Um software onde todos os elementos são desacoplatos uns dos outros não pode fazer nada. Todo sistema exibe, e deve exibir, acoplamento, no mesmo sentido em que todo sistema, não importa quão independente de plataforma, depende de alguma plataforma.

Mau acoplamento é mau design, causado por mau projetistas. Nem orientação a subrotinas, nem orientação a objetos, a componentes, ou a aspectos é causador disso. Dizer o contrário é como dizer que um poema é feio por culpa do português.

--
 P.

Ponto V! - Vinícius Godoy

unread,
Jan 28, 2013, 9:14:02 AM1/28/13
to ccppb...@googlegroups.com
Acho que a principal diferença entre o estático e o dinâmico está no fato de você precisar ou não daquele polimorfismo em runtime.

Se a decisão é só do programador, no momento da implementação do software, o polimorfismo estático resolve na maioria das vezes. 

Agora, se a decisão não está na sua mão, e você só vai descobrir com base em alguma informação fornecida pelo cliente, e você não pretende refazer um build só para ele, aí, tem que apelar para algum tipo de polimorfismo dinâmico.

Att,

Vinícius

Vinícius Godoy de Mendonça
@vinigodoy

Ponto V! - Programação de Jogos Profissional
www.pontov.com.br - @pontov - Facebook



--
--
Antes de enviar um e-mail para o grupo leia:
http://www.ccppbrasil.org/wiki/Lista:AntesdePerguntar
--~--~---------~--~----~---------------------------------~----------~--~----~
[&] Colabore com a Pesquisa de Preferência de Conteúdo
para Eventos do Grupo C & C++ Brasil:
http://www.surveymonkey.com/s/GBBGTXN
------~----~-------~---~---~---~---~----------------~------------~---------~
[&] C & C++ Brasil - http://www.ccppbrasil.org/
Para sair dessa lista, envie um e-mail para ccppbrasil-...@googlegroups.com
Para mais opções, visite http://groups.google.com/group/ccppbrasil
--~--~---------~--~----~--~-~--~---~----~-----------------~--~----------~
Emprego & carreira: vag...@ccppbrasil.org
http://groups.google.com/group/dev-guys?hl=en
 
---
Você está recebendo esta mensagem porque se inscreveu no grupo "ccppbrasil" dos Grupos do Google.
Para cancelar a inscrição nesse grupo, envie um e-mail para ccppbrasil+...@googlegroups.com.
Para obter mais opções, acesse https://groups.google.com/groups/opt_out.
 
 

Уθя¡ςκ

unread,
Jan 28, 2013, 9:29:49 AM1/28/13
to ccppb...@googlegroups.com
O OO do C++ foi criado com a premissa do 0 overhead (ou quase 0 quando entra em cena uma vtable). "0 overhead" é uma lema de peso pra linguagem C++, qualquer feature que surge sempre tentar conservar este lema. Aqui "0 overhead" se dá sobre o equivalente C do código (overhead do OO C++ == overhead do OO C).

O OO do C++ é fundamentalmente diferente de outras linguagens como Smalltalk, Objective-C e Go, onde métodos são mensagens enviadas a objetos, e não é necessário o acoplamento por herança, basta o objeto responder ou não a mensagem. Isso pode trazer tanto vantagens quanto problemas. Porém conseguir "0 overhead" através deste paradigma é outra história. O OO do Smalltalk, seguido pelo Objective-C, (a.k.a. duck typing) é um mecanismo existente diretamente na linguagem que atinge de certa forma algum dos pontos que você levanta.

C++ possui uma forma de duck typing em compile time via templates e concepts porém não em runtime, e este duck typing é "0 overhead" (pra execução, vamos ignorar tamanho do arquivo objeto e tempo de compilação).

Thiago Adams

unread,
Jan 28, 2013, 10:35:48 AM1/28/13
to ccppbrasil


On Jan 28, 11:39 am, "P." <pedro.lama...@gmail.com> wrote:
> Em domingo, 27 de janeiro de 2013 18h22min35s UTC-2, Thiago Adams escreveu:
>
>
>
> > Um assunto que me chama bastante atenção são as questões relativas ao
> > polimorfismo dinâmico. Ao mesmo tempo que representa uma solução ele
> > também representa
> > um problema de acoplamento e dificuldade de re-uso.
>
> > Algo ruim da OOP é o acoplamento criado pelas heranças.
>
> Algo ruim em que sentido? Um software onde todos os elementos são
> desacoplatos uns dos outros não pode fazer nada. Todo sistema exibe, e deve
> exibir, acoplamento, no mesmo sentido em que todo sistema, não importa quão
> independente de plataforma, depende de alguma plataforma.


O exemplo que gosto de usar é a criação de um Botão gráfico.
O botão pode ser desenvolvido basicamente como uma classe concreta
estilo vector e ser bem reutilizável de fácil criação e manutenção.

O problema começa quando ele precisa ser inserido em uma lista
polimórfica da árvore vísual da tela.
Neste caso entram todos os algorítmos que serão aplicados na árvore de
forma genérica e o botão precisa fazer parte deste contexto todo
através
das virtuais que serão suas partes usadas de forma polimórfica.



P.

unread,
Jan 28, 2013, 10:38:17 AM1/28/13
to ccppb...@googlegroups.com


Em segunda-feira, 28 de janeiro de 2013 09h38min46s UTC-2, Thiago Adams escreveu:

O problema só existe no polimorfismo dinâmico, pois o polimorfismo
estático não necessita herança.

Polimorfismo estático exige a conformidade dos argumentos-de-template com os inexpressáveis "conceitos".
Se você diz "polimorfismo estático", eu digo "herança estática".
O fato de não existir sintaxe para expressar essa relação não é um bônus, é um defeito.
A relação em si é muito útil, é claro, e nós usamos todos os dias.

--
 P.

Thiago Adams

unread,
Jan 28, 2013, 10:40:22 AM1/28/13
to ccppbrasil
Perfeito! Estamos falando a mesma lingua.
Em C ou C++ é possível usar o estilo de mensagens e conseguir o
polimorfimo.
Isto é usado na API do windows com as SendMessage.
Tem overhead claro, mas não deixa de ser uma alternativa.





Felipe Magno de Almeida

unread,
Jan 28, 2013, 10:42:33 AM1/28/13
to ccppb...@googlegroups.com
2013/1/28 Ponto V! - Vinícius Godoy <vini...@pontov.com.br>
>
> Acho que a principal diferença entre o estático e o dinâmico está no fato de você precisar ou não daquele polimorfismo em runtime.
>
> Se a decisão é só do programador, no momento da implementação do software, o polimorfismo estático resolve na maioria das vezes.
>
> Agora, se a decisão não está na sua mão, e você só vai descobrir com base em alguma informação fornecida pelo cliente, e você não pretende refazer um build só para ele, aí, tem que apelar para algum tipo de polimorfismo dinâmico.

Você sempre pode usar o polimorfismo dinâmico sobre o polimorfismo
estático, mas nunca o contrário.

> Att,
>
> Vinícius
>
> Vinícius Godoy de Mendonça
> @vinigodoy

[]'s
--
Felipe Magno de Almeida

Felipe Magno de Almeida

unread,
Jan 28, 2013, 10:43:44 AM1/28/13
to ccppb...@googlegroups.com
2013/1/28 Уθя¡ςκ <obl...@gmail.com>:
> O OO do C++ foi criado com a premissa do 0 overhead (ou quase 0 quando entra
> em cena uma vtable). "0 overhead" é uma lema de peso pra linguagem C++,
> qualquer feature que surge sempre tentar conservar este lema. Aqui "0
> overhead" se dá sobre o equivalente C do código (overhead do OO C++ ==
> overhead do OO C).

A premissa é "You only pay for what you use". Virtual tables tem overhead,
mas só quando você usa.

[snip]

Thiago Adams

unread,
Jan 28, 2013, 10:45:06 AM1/28/13
to ccppbrasil
A conformidade com o conceito no caso de polimorfismo estático não é
"intrusivo" como no caso das funções virtuais.
Este é um dos problemas de acoplamento das interfaces, a classe
precisa "saber" e querer ser polimorfica. Ela não tem escolha de uma
hora ser usada de forma polimorfica e outra hora não ser.






Felipe Magno de Almeida

unread,
Jan 28, 2013, 10:46:59 AM1/28/13
to ccppb...@googlegroups.com
2013/1/28 P. <pedro....@gmail.com>:
>
> Em segunda-feira, 28 de janeiro de 2013 09h38min46s UTC-2, Thiago Adams
> escreveu:
>>
>> O problema só existe no polimorfismo dinâmico, pois o polimorfismo
>> estático não necessita herança.
>
> Polimorfismo estático exige a conformidade dos argumentos-de-template com os
> inexpressáveis "conceitos".

Por que inexpressaveis?

> Se você diz "polimorfismo estático", eu digo "herança estática".

Herança?

> O fato de não existir sintaxe para expressar essa relação não é um bônus, é
> um defeito.

Qual é o defeito?

> A relação em si é muito útil, é claro, e nós usamos todos os dias.

IMO, muito mais útil que a extremamente limitante polimorfismo dinâmico.
E que tem o mesmo problema que o polimorfismo estático de não ser
possível construir constraints semânticos. Aonde o polimorfismo dinâmico
é uma vantagem sobre o polimorfismo estático?

> --
> P.

[]'s

Thiago Adams

unread,
Jan 28, 2013, 10:47:34 AM1/28/13
to ccppbrasil


On Jan 28, 1:43 pm, Felipe Magno de Almeida
Você não tem a liberdade de usar a mesma clase hora de forma
polimorfica hora de forma não polimórfica. Isso é um tipo de
acoplamento.

Felipe Magno de Almeida

unread,
Jan 28, 2013, 10:48:09 AM1/28/13
to ccppb...@googlegroups.com
2013/1/28 Thiago Adams <thiago...@gmail.com>:
Ou usar tipos construidos por terceiros como modelo em um algoritmo.
Já que a classe teria que herdar de uma que não tem conhecimento.

> --

Felipe Magno de Almeida

unread,
Jan 28, 2013, 10:49:31 AM1/28/13
to ccppb...@googlegroups.com
2013/1/28 Thiago Adams <thiago...@gmail.com>:
Eu estava mencionando que não é uma premissa de zero overhead. E sim
de só pagar pelo que se usa. Não disse nada sobre acoplamento.

> --

[]'s

Уθя¡ςκ

unread,
Jan 28, 2013, 10:58:42 AM1/28/13
to ccppb...@googlegroups.com
On Monday, January 28, 2013 1:49:31 PM UTC-2, Felipe Magno de Almeida wrote:
Eu estava mencionando que não é uma premissa de zero overhead. E sim 
de só pagar pelo que se usa. Não disse nada sobre acoplamento.

Felipe Magno de Almeida

"Pagar pelo que se usa" é uma premissa, você pode ou não pagar ao fazer uso ou não de virtual tables. Porém, "0 overhead" têm também faz parte, pois sempre se busca "pagar pouco ou nada" nas alternativas que são oferecidas.

Thiago Adams

unread,
Jan 28, 2013, 11:02:05 AM1/28/13
to ccppbrasil

Uma das alternaticas para o polimorfismo é a seguinte:

Duas classes concretas Button e Label de simples manutenção sem
acoplamento.

class Button
{
friend void Draw(const Button&);
};
void Draw(const Button&)
{
cout << "button";
}

class Label
{
friend void Draw(const Label&);
};
void Draw(const Label&)
{
cout << "label";
}

//Preciso agora um algoritmo polimorfico que faça Draw de items
polimorficos

struct IControl
{
virtual void Draw() = 0;
};


//Mecanica de um adaptador de interface.

template<class Interface, class Object> struct InterfaceCast;

template<class Object>
struct InterfaceCast<IControl, Object> : public IControl
{
Object obj;
virtual void Draw() override
{
::Draw(obj);
}
};

//Uso de um adaptador

int main()
{
std::vector<std::unique_ptr<IControl>> v;
v.emplace_back(new InterfaceCast<IControl, Button>());
v.emplace_back(new InterfaceCast<IControl, Label>());

for (auto & item : v)
{
item->Draw();
}
}

Neste caso a decisão da interface está no algorimo (Draw all) e não
nos objetos.
A forma de storage e o algorimo definem a interface e não o objeto.

Ponto V! - Vinícius Godoy

unread,
Jan 28, 2013, 11:09:40 AM1/28/13
to ccppb...@googlegroups.com
Com certeza, é possível usar polimorfismo dinâmico sobre o estático. 
Mas aí está pagando pela complexidade dos dois modelos, e da integração deles.


Em 28 de janeiro de 2013 13:42, Felipe Magno de Almeida <felipe.m...@gmail.com> escreveu:

Você sempre pode usar o polimorfismo dinâmico sobre o polimorfismo
estático, mas nunca o contrário.

> Att,
>
> Vinícius
>
> Vinícius Godoy de Mendonça
> @vinigodoy

[]'s
--
Felipe Magno de Almeida
--
--
Antes de enviar um e-mail para o grupo leia:
                     http://www.ccppbrasil.org/wiki/Lista:AntesdePerguntar
--~--~---------~--~----~---------------------------------~----------~--~----~
[&] Colabore com a Pesquisa de Preferência de Conteúdo
              para Eventos do Grupo C & C++ Brasil:
                        http://www.surveymonkey.com/s/GBBGTXN
------~----~-------~---~---~---~---~----------------~------------~---------~
[&] C & C++ Brasil - http://www.ccppbrasil.org/
Para sair dessa lista, envie um e-mail para ccppbrasil-...@googlegroups.com
Para mais opções, visite http://groups.google.com/group/ccppbrasil
--~--~---------~--~----~--~-~--~---~----~-----------------~--~----------~
Emprego & carreira:  vag...@ccppbrasil.org
http://groups.google.com/group/dev-guys?hl=en

---
Você está recebendo esta mensagem porque se inscreveu no grupo "ccppbrasil" dos Grupos do Google.
Para cancelar a inscrição neste grupo e parar de receber seus e-mails, envie um e-mail para ccppbrasil+...@googlegroups.com.

Thiago Adams

unread,
Jan 28, 2013, 11:23:05 AM1/28/13
to ccppbrasil

Melhorando o exemplo:

São pequenos problemas resolvidos separadamente.


using namespace std;

class Button { };

void Draw(const Button&)
{
cout << "button" << endl;
}

class Label { };

void Draw(const Label&)
{
cout << "label" << endl;
}

struct IControl { virtual void Draw() = 0; };
void Draw(IControl* p) { p->Draw(); }

void Draw(std::unique_ptr<IControl>& p)
{
p->Draw();
}

template<class Interface, class Object> struct InterfaceCast;

template<class Object>
struct InterfaceCast<IControl, Object> : public IControl
{
Object obj;
virtual void Draw() override {
::Draw(obj);
}
};

void Draw(int i)
{
cout << i << endl;
}

//Algoritmo

template <class T>
void DrawAll(T& v)
{
for (auto & item : v)
{
Draw(item);
}
}


int main()
{
std::vector<std::unique_ptr<IControl>> v;
v.emplace_back(new InterfaceCast<IControl, Button>());
v.emplace_back(new InterfaceCast<IControl, Label>());

DrawAll(v);

std::vector<Button> buttons;
buttons.emplace_back(Button());
buttons.emplace_back(Button());


DrawAll(buttons);

std::vector<int> ints;
ints.emplace_back(1);
ints.emplace_back(2);


DrawAll(ints);
}

Notem que button foi usado ao mesmo tempo em um contexto polimorfico e
outro não polimorfico.


P.

unread,
Jan 28, 2013, 12:16:45 PM1/28/13
to ccppb...@googlegroups.com
Em segunda-feira, 28 de janeiro de 2013 14h02min05s UTC-2, Thiago Adams escreveu:
 
//Uso de um adaptador


Se um adaptador é permitido, o mesmo nível de flexibilidade pode ser obtido com polimorfismo dinâmico, como demonstrado no GoF.


--
 P.

Thiago Adams

unread,
Jan 28, 2013, 12:41:30 PM1/28/13
to ccppb...@googlegroups.com



2013/1/28 P. <pedro....@gmail.com>

Em segunda-feira, 28 de janeiro de 2013 14h02min05s UTC-2, Thiago Adams escreveu:
 
//Uso de um adaptador


Se um adaptador é permitido, o mesmo nível de flexibilidade pode ser obtido com polimorfismo dinâmico, como demonstrado no GoF.


Não entendi.
Este é dinâmico.
O adaptador só remove dos objetos a responsabilidade da interface e coloca o problema no algorítmo e "storage". É possível fazer sem templates, mas não é isso que deixa dinâmico ou estático, é apenas um conveniência na criação do adaptador.

Thiago Adams

unread,
Jan 28, 2013, 12:45:39 PM1/28/13
to ccppbrasil
Na verdade esta discussão é também a continuação da "Pitfalls of
Object Oriented Programming"

Neste caso do adaptador existe uma mudança no paradigma na minha
opnião.
O foco sai do objeto e passa para os algorímos.

O adaptador não precisa fazer sentido como uma entidade em um diagrama
UML.
O adaptador é um detalhe de implementaçã que permite em runtime a
seleção da função mais adequada para o trabalho.
É como a dedução do melhor tipo em um template, só que dinamicamente.

Felipe Magno de Almeida

unread,
Jan 28, 2013, 12:45:39 PM1/28/13
to ccppb...@googlegroups.com
2013/1/28 Ponto V! - Vinícius Godoy <vini...@pontov.com.br>:
> Com certeza, é possível usar polimorfismo dinâmico sobre o estático.
> Mas aí está pagando pela complexidade dos dois modelos, e da integração
> deles.

Não vejo complexidade adicionada. Nesse caso o polimorfismo dinâmico vira
detalhe de implementação do modelo.

Thiago Adams

unread,
Jan 28, 2013, 12:51:01 PM1/28/13
to ccppbrasil

On Jan 28, 3:45 pm, Felipe Magno de Almeida
<felipe.m.alme...@gmail.com> wrote:
> 2013/1/28 Ponto V! - Vinícius Godoy <vinigo...@pontov.com.br>:
>
> > Com certeza, é possível usar polimorfismo dinâmico sobre o estático.
> > Mas aí está pagando pela complexidade dos dois modelos, e da integração
> > deles.
>
> Não vejo complexidade adicionada. Nesse caso o polimorfismo dinâmico vira
> detalhe de implementação do modelo.

O outro detalhe em relação a discussão anterior "Pitfalls of
Object Oriented Programming" é que se existe um adaptador já é
possível usar a "forma universal" de função aplicada sobre um objeto
mesmo no caso de virtuais.
Por isso, usei o exemplo com ints.



P.

unread,
Jan 28, 2013, 12:55:59 PM1/28/13
to ccppb...@googlegroups.com

Em segunda-feira, 28 de janeiro de 2013 15h41min30s UTC-2, Thiago Adams escreveu:

2013/1/28 P. <pedro....@gmail.com>


Se um adaptador é permitido, o mesmo nível de flexibilidade pode ser obtido com polimorfismo dinâmico, como demonstrado no GoF.


Não entendi.
Este é dinâmico.
O adaptador só remove dos objetos a responsabilidade da interface e coloca o problema no algorítmo e "storage". É possível fazer sem templates, mas não é isso que deixa dinâmico ou estático, é apenas um conveniência na criação do adaptador.

Não expressar Draw como classe base de IControl é a decisão inicial neste design. Ela parece se justificar diante da possibilidade de escrever InterfaceCast para tornar os objetos úteis. Se eu estou entendendo bem o contexto, estamos tratando de uma inflexibilidade do polimorfismo dinâmico. Eu estou dizendo que se um adaptador é permitido, então os supostos problemas não existem. Se eu tenho um IButton da biblioteca IControl mas quero usá-lo com um algortimo da biblioteca foo_control posso escrever um adaptador segundo a técnica descrita no GoF.

--
 P.

Thiago Adams

unread,
Jan 28, 2013, 1:26:05 PM1/28/13
to ccppbrasil


On Jan 28, 3:55 pm, "P." <pedro.lama...@gmail.com> wrote:
> Em segunda-feira, 28 de janeiro de 2013 15h41min30s UTC-2, Thiago Adams
> escreveu:
>
>
>
> > 2013/1/28 P. <pedro....@gmail.com <javascript:>>
>
> >> Se um adaptador é permitido, o mesmo nível de flexibilidade pode ser
> >> obtido com polimorfismo dinâmico, como demonstrado no GoF.
>
> > Não entendi.
> > Este é dinâmico.
> > O adaptador só remove dos objetos a responsabilidade da interface e coloca
> > o problema no algorítmo e "storage". É possível fazer sem templates, mas
> > não é isso que deixa dinâmico ou estático, é apenas um conveniência na
> > criação do adaptador.
>
> Não expressar Draw como classe base de IControl é a decisão inicial neste
> design. Ela parece se justificar diante da possibilidade de escrever
> InterfaceCast para tornar os objetos úteis.

Mesmo na forma não polimorfica o objeto é útil.

>Se eu estou entendendo bem o
> contexto, estamos tratando de uma inflexibilidade do polimorfismo dinâmico.
> Eu estou dizendo que se um adaptador é permitido, então os supostos
> problemas não existem. Se eu tenho um IButton da biblioteca IControl mas
> quero usá-lo com um algortimo da biblioteca foo_control posso escrever um
> adaptador segundo a técnica descrita no GoF.

Neste caso o objeto pode ser reutilizado mas a complexidade dos
acoplamentos na origem permanesse. Não se tem um pequeno problema para
se resolver de cada vez. Interfaces e heranças são um problema de
"balanceamento" iterativo e conceitual.

Este problema também vai existir no adaptador. É um processo
iterativo. A cada novo algoritmo aplicado a lista polimorfica é
preciso uma mudança no adaptador e na interface. Porem estes dois não
são uma entidate logica bonita e sim um detalhe de implementacao.
Todas as funcoes estao no adaptador e não precisariam ser divididas em
interfaces lógicas separadas .
Por exemplo, se existe o método save/ load, seria na interface
IControl ou uma nova ISaveLoad?
O eventos de teclado seriam na IKeyboardEvents ou seria apenas uma
IEvents com mouse e teclado juntos? Ou seria tudo junto na IControl?



P.

unread,
Jan 28, 2013, 2:16:59 PM1/28/13
to ccppb...@googlegroups.com

Em segunda-feira, 28 de janeiro de 2013 16h26min05s UTC-2, Thiago Adams escreveu:

On Jan 28, 3:55 pm, "P." <pedro.lama...@gmail.com> wrote:
> Em segunda-feira, 28 de janeiro de 2013 15h41min30s UTC-2, Thiago Adams
> escreveu:
>
>
>
> > 2013/1/28 P. <pedro....@gmail.com <javascript:>>
>
> >> Se um adaptador é permitido, o mesmo nível de flexibilidade pode ser
> >> obtido com polimorfismo dinâmico, como demonstrado no GoF.
>
> > Não entendi.
> > Este é dinâmico.
> > O adaptador só remove dos objetos a responsabilidade da interface e coloca
> > o problema no algorítmo e "storage". É possível fazer sem templates, mas
> > não é isso que deixa dinâmico ou estático, é apenas um conveniência na
> > criação do adaptador.
>
> Não expressar Draw como classe base de IControl é a decisão inicial neste
> design. Ela parece se justificar diante da possibilidade de escrever
> InterfaceCast para tornar os objetos úteis.

Mesmo na forma não polimorfica o objeto é útil.


Sim. E o fato de esse mesmo objeto ser tornado polimórfico não o torna menos útil.
 

>Se eu estou entendendo bem o
> contexto, estamos tratando de uma inflexibilidade do polimorfismo dinâmico.
> Eu estou dizendo que se um adaptador é permitido, então os supostos
> problemas não existem. Se eu tenho um IButton da biblioteca IControl mas
> quero usá-lo com um algortimo da biblioteca foo_control posso escrever um
> adaptador segundo a técnica descrita no GoF.

Neste caso o objeto pode ser reutilizado mas a complexidade dos
acoplamentos na origem permanesse.


De que complexidade nós estamos falando?

Da presença de um nome explicitamente indicado no texto do programa?

std::for_each exibe acoplamento a um conjunto de regras cuja expressão não possui sintaxe em C++ e a comunidade convencionou chamar conceito ForwardIterator. Todo argumento-de-template usado com std::for_each deve obedecer a esse conjunto de regras e portanto isso participa de uma relação é-um com aquilo i.e. sua classe iterador é-um ForwardIterator. É perfeitamente possível construir um algoritmo genérico-em-runtime equivalente. Nesse caso, o modo de genericidade oferecido pelos templates é muito superior.

Essa superioridade não é infinita. Um sistema em diversas camadas -- digamos um sistema de gestão de recursos XPTO -- geralmente decide certos itens de configuração na camada mais rasa e injeta referência ao recurso (ou um alocador de recursos) nas camadas mais inferiores. Esta técnica, se aplicada com templates, exigiria que absolutamente todas os elementos entre a camada rasa e a camada profunda fosse um template com um argumento correspondendo ao item injetado. Se três itens forem injetados, cada uma dessas exige três argumentos de template. Isso é típico para alocadores de recurso como um pool de conexões de banco de dados, um tracer ou logger, um alocador de sessões de correio etc. Você diria que genericidade-de-compilação é superior na expressão desse tipo de sistema? Eu digo que não. E nem entramos ainda em questões de provisionamento de componentes etc.

--
 P.

Felipe Magno de Almeida

unread,
Jan 28, 2013, 2:45:50 PM1/28/13
to ccppb...@googlegroups.com
2013/1/28 P. <pedro....@gmail.com>:
>

[snip]

> std::for_each exibe acoplamento a um conjunto de regras cuja expressão não
> possui sintaxe em C++ e a comunidade convencionou chamar conceito
> ForwardIterator.

Esse "conjunto de regras" se chama semântica. E não existe uma expressão
sintática porque não tem nada a ver com sintaxe. Da mesma forma que você
definirá qual comportamento cada função de uma interface tem, você o faz
para os modelos de um conceito. Se numa implementação de uma interface
polimórfica aonde a função next não avançar, então ele quebra as
expectativas dos algoritmos e gerará undefined behavior da mesma forma
como operator++. Mas, ao contrário do polimorfismo dinâmico, o uso
de objetos por valor é perfeitamente viável, o que diminui a complexidade
por evitar o aliasing desnecessário e facilitar o reasoning de código por
não ter que levar em consideração esse aliasing incidental.

[snip]

> --
> P.
>
> --
> --
> Antes de enviar um e-mail para o grupo leia:
> http://www.ccppbrasil.org/wiki/Lista:AntesdePerguntar
> --~--~---------~--~----~---------------------------------~----------~--~----~
> [&] Colabore com a Pesquisa de Preferência de Conteúdo
> para Eventos do Grupo C & C++ Brasil:
> http://www.surveymonkey.com/s/GBBGTXN
> ------~----~-------~---~---~---~---~----------------~------------~---------~
> [&] C & C++ Brasil - http://www.ccppbrasil.org/
> Para sair dessa lista, envie um e-mail para
> ccppbrasil-...@googlegroups.com
> Para mais opções, visite http://groups.google.com/group/ccppbrasil
> --~--~---------~--~----~--~-~--~---~----~-----------------~--~----------~
> Emprego & carreira: vag...@ccppbrasil.org
> http://groups.google.com/group/dev-guys?hl=en
>
> ---
> Você está recebendo esta mensagem porque se inscreveu no grupo "ccppbrasil"
> dos Grupos do Google.
> Para cancelar a inscrição nesse grupo, envie um e-mail para

Thiago Adams

unread,
Jan 28, 2013, 8:44:51 PM1/28/13
to ccppb...@googlegroups.com


Em segunda-feira, 28 de janeiro de 2013, P. escreveu:

Em segunda-feira, 28 de janeiro de 2013 16h26min05s UTC-2, Thiago Adams escreveu:

On Jan 28, 3:55 pm, "P." <pedro.lama...@gmail.com> wrote:
> Em segunda-feira, 28 de janeiro de 2013 15h41min30s UTC-2, Thiago Adams
> escreveu:
>
>
>
> > 2013/1/28 P. <pedro....@gmail.com <javascript:>>
>
> >> Se um adaptador é permitido, o mesmo nível de flexibilidade pode ser
> >> obtido com polimorfismo dinâmico, como demonstrado no GoF.
>
> > Não entendi.
> > Este é dinâmico.
> > O adaptador só remove dos objetos a responsabilidade da interface e coloca
> > o problema no algorítmo e "storage". É possível fazer sem templates, mas
> > não é isso que deixa dinâmico ou estático, é apenas um conveniência na
> > criação do adaptador.
>
> Não expressar Draw como classe base de IControl é a decisão inicial neste
> design. Ela parece se justificar diante da possibilidade de escrever
> InterfaceCast para tornar os objetos úteis.

Mesmo na forma não polimorfica o objeto é útil.


Sim. E o fato de esse mesmo objeto ser tornado polimórfico não o torna menos útil.
 

Obriga a levar as interfaces junto. O ajuste das interfaces para quem desenvolve o objeto leva tempo e no fim ainda será algo acoplado. Ex iostreams.

 
>Se eu estou entendendo bem o
> contexto, estamos tratando de uma inflexibilidade do polimorfismo dinâmico.
> Eu estou dizendo que se um adaptador é permitido, então os supostos
> problemas não existem. Se eu tenho um IButton da biblioteca IControl mas
> quero usá-lo com um algortimo da biblioteca foo_control posso escrever um
> adaptador segundo a técnica descrita no GoF.

Neste caso o objeto pode ser reutilizado mas a complexidade dos
acoplamentos na origem permanesse.


De que complexidade nós estamos falando?

Da presença de um nome explicitamente indicado no texto do programa?

Acoplamentos devido a heranças. Dificuldade de criação e manutenção.



--
www.thradams.com

Walter Mascarenhas

unread,
Jan 28, 2013, 8:53:34 PM1/28/13
to ccppb...@googlegroups.com
 Completando esta última resposta do Felipe ao Pedro e também
comentando sobre o duck typing mencionado pelo  Уθя¡ςκ :

 É possível sim expressar, a semântica envolvida nestas abstrações
de modo a refletir mais que duck typing puro e simples, pelo
menos no caso específico no qual estou trabalhando atualmente.. 

  Por exemplo, usando um pouco de template aliases e enable_if
dá para escrever algo assim

template <typename X>
UseIf< IsVectorSpace<X>, X >
operator+(X const& a, X const& b){...}


de modo a definir um operator+ que se aplica
a elementos de um espaço vetorial, que é um
conceito muito preciso para matemáticos como eu.
Ou seja, pelo menos no meu caso, consigo emprestar
a semântica da matemática para explicitar o que quero.

   Com o tempo também acredito que apareceráo formas
naturais de se expressar esta semântica em outras
áreas de aplicação. 

Thiago Adams

unread,
Jan 28, 2013, 9:14:20 PM1/28/13
to ccppb...@googlegroups.com
O problema pode ser visto assim:
vtables são eficientes para implementar o polimorfismo. A vtable é definida através da interface virtual.
Dado os objetos a, b, c cada um com funções, existe um conjunto de funções comuns entre a, b e c aptas ao polimorfismo.
Nem todo algoritmo precisa deste conjunto todo.
Por exemplo, o algoritmo draw_all, precisa só da draw.
O algoritmo load_all precisa só da "load" e algoritmo save_all só da save.
Poderia ter sido criada uma interface com todos os métodos comuns (draw, save, load). Ao passar esta interface para um algoritmo esta se criando acoplamento pois load_all não precisa da draw.
Ao separar as interfaces em pedaços menores também se cria acoplamento pois a combinação feita para um programa pode não ser a melhor para outro. Ou seja, a própria combinação pode criar um acoplamento desnecessário



--
www.thradams.com

P.

unread,
Jan 29, 2013, 7:05:06 AM1/29/13
to ccppb...@googlegroups.com


Em segunda-feira, 28 de janeiro de 2013 17h45min50s UTC-2, Felipe Magno de Almeida escreveu:
2013/1/28 P. <pedro....@gmail.com>:

[snip]

> std::for_each exibe acoplamento a um conjunto de regras cuja expressão não
> possui sintaxe em C++ e a comunidade convencionou chamar conceito
> ForwardIterator.

Esse "conjunto de regras" se chama semântica. E não existe uma expressão
sintática porque não tem nada a ver com sintaxe.


Ora, por favor, não existe uma expressão sintática porque não existe uma expressão sintática. C++ é apenas e tão somente pobre na expressão dos argumentos de um template. Sugerir que de algum modo templates são uma maravilha metafísica extrasintática não é sensato. Programadores assembler escreviam subrotinas muito antes de exitir uma sintaxe específica para subrotinas. Você pretende conceder a eles que subrotinas não tem nada a ver com sintaxe também? O Elements of Programming do Stepanov e McJones é suficiente para convencer qualquer um da necessidade de representar o elemento (que a comunidade do C++ veio a chamar "conceito", não "semântica") que constrange todo argumento-de-template possível para qualquer template. É uma ilusão esta imagem onde polimorfismo-dinâmico tem constrição pela classe base e polimorfismo-estático não tem constrição nenhuma, que polimorfismo-dinâmico é "complexo" e polimorfismo-estático é "simples".

--
 P.

Thiago Adams

unread,
Jan 29, 2013, 7:46:51 AM1/29/13
to ccppbrasil

On Jan 29, 10:05 am, "P." <pedro.lama...@gmail.com> wrote:
...
É uma ilusão esta imagem onde polimorfismo-dinâmico tem
> constrição pela classe base e polimorfismo-estático não tem constrição
> nenhuma, que polimorfismo-dinâmico é "complexo" e polimorfismo-estático é
> "simples".

Existe diferença. Citei o exemplo do draw, load, save.

Posso citar mais exemplos.

Imagine IControl com o evento virtual OnKeyDown no programa 1.

Outro programa, o programa 2, resolveu fazer seu próprio IControl2
pois tinha coisas que não serviam no IControl 1. Trocou o Draw por
exemplo.

Toda a rotina de despachar mensagens de teclado do programa 2 é igual
do programa 1. Porém os algoritmos foram feito para IControl que não
será usado no programa 2.

Se ao invés do evento virtual OnKeyDown ter sido criado na interface
IControl tivesse sido criado em um IKeyboardEvents esta interface
poderia ter sido usad sem mudanças no programa 2. Mas como se iria
saber no programa 1?
Naquele programa fazia sentido.

Se o motivo da criação da IControl 2 foi a Draw, então seria melhor
que se tivesse criado uma IDraw ao invés de colocar virtual Draw na
interface IControl.

Enfim, espero que fique claro que não é fácil fazer mudanças quando
existe heranças.

Já no caso dos templates, se o objeto concreto tem OnKeyDown, não
importa se era de uma interface IControl ou IKeyboardEvent, o que
importa é que ele está lá no objeto. O Draw é a mesma coisa.











Felipe Magno de Almeida

unread,
Jan 29, 2013, 9:54:48 AM1/29/13
to ccppb...@googlegroups.com
2013/1/29 P. <pedro....@gmail.com>:
>
> Em segunda-feira, 28 de janeiro de 2013 17h45min50s UTC-2, Felipe Magno de
> Almeida escreveu:
>>
>> 2013/1/28 P. <pedro....@gmail.com>:
>>
>> [snip]
>>
>> > std::for_each exibe acoplamento a um conjunto de regras cuja expressão
>> > não
>> > possui sintaxe em C++ e a comunidade convencionou chamar conceito
>> > ForwardIterator.
>>
>> Esse "conjunto de regras" se chama semântica. E não existe uma expressão
>> sintática porque não tem nada a ver com sintaxe.
>
>
>
> Ora, por favor, não existe uma expressão sintática porque não existe uma
> expressão sintática.

Qual a diferença entre um input iterator e um forward iterator? Como você
poderia expressar isso sintáticamente sendo que a diferença se encontra
nos requisitos semânticos dos operadores operator* e operator++?
Sintaticamente eles tem diferença em std::iterator_traits<T>::category,
mas sua diferença reral é somente semântica.
A única saída que existe, que você criticou é dar nomes. Assim como é
feito com polimorfismo dinâmico: você constroi a classe base, dá um nome
a ela, e diz quais são os requisitos semânticos de cada função-membro.
A diferença é que no polimorfismo dinâmico você trabalha com um único
tipo estático, enquanto com GP você trabalha com infinitos tipos
estáticos. Mas, os requisitos semanticos continuam fazendo parte do
conceito e são inexpressíveis em código por conta da derivação do
halt problem.

> C++ é apenas e tão somente pobre na expressão dos
> argumentos de um template.

C++ não possui "tipos de tipos" ainda. O que é uma pena, mas não
torna polimorfismo dinâmico nem um pouco melhor por conta disto.

> Sugerir que de algum modo templates são uma
> maravilha metafísica extrasintática não é sensato.

Nunca falei isso. E sim, não é sensato. Asism como não seria
sensato afirmar isso de polimorfismo dinâmico também.

> Programadores assembler
> escreviam subrotinas muito antes de exitir uma sintaxe específica para
> subrotinas.

E daí?

> Você pretende conceder a eles que subrotinas não tem nada a ver
> com sintaxe também?

Não sei de onde você tirou isso, mas tenho certeza que não afirmei isto,
e muito menos entendo qual seu ponto com essa pergunta.

> O Elements of Programming do Stepanov e McJones é
> suficiente para convencer qualquer um da necessidade de representar o
> elemento (que a comunidade do C++ veio a chamar "conceito", não "semântica")
> que constrange todo argumento-de-template possível para qualquer template.

Poder construir constraints de conceitos seria uma boa feature que facilitaria
na construção de sobrecargas (sem uso de tag dispatching e/ou SFINAE).
Mas, o seguinte continuaria não sendo uma critica que faria o polirmofismo
dinamico ser melhor que o estático:

"std::for_each exibe acoplamento a um conjunto de regras cuja expressão não
possui sintaxe em C++ e a comunidade convencionou chamar conceito
ForwardIterator."

A única forma de diferenciar um ForwardIterator de um InputIterator é
pelo próprio desenvolvedor de determinada classe, já que a *única*
diferenciação não é sintática e somente semântica. E, se seu bashing
de GP advém de não ser possível diferenciar um ForwardIterator em código,
isso também está errado, já que seria só olhar por category em
std::iterator_traits e SFINAE a inexistencia do mesmo.

De qualquer forma o convencionamento de nomear o conjunto de
semânticas, com concepts nativo a linguagem ou com polimorfismo
dinâmico continua o mesmo. Se eu explicit specialize iterator_traits
de istream_iterator<double> e colocar a category como forward_iterator
terei undefined behavior da mesma forma que se alguém quebrar
as regras semanticas de uma função-membro virtual.

E, para verificação de que determinado tipo *diz* modelar determinado
conceito, é de praxe que o conceito defina uma meta-função que diga
se é daquele conceito ou não.

Aonde is_math_3d_vector<T>::value é um bool. O que certamente
facilita. Mas sua falta não torna GP menos útil e polimorfismo dinâmico
mais útil como método de acoplamento entre partes díspares de
um programa. Vejo que você não

> É uma ilusão esta imagem onde polimorfismo-dinâmico tem constrição
> pela classe base e polimorfismo-estático não tem constrição nenhuma, que
> polimorfismo-dinâmico é "complexo" e polimorfismo-estático é "simples".

Não consegui parsear, e acho que ninguém afirmou que polimorfismo estático
é simples e nem que não tem constrição nenhuma.

Quanto a polimorfismo-dinâmico ser complexo, ele não é complexo per se,
mas traz complexidade
incidental desnecessária como a necessidade de se usar wrappers,
construção de aliasing e a comum necessidade de se "reatrelar" o objeto a um
escopo através de um smart pointer, aonde passar por valor seria não só
suficiente, mas mais claro. Não incomumente esse aliasing acaba gerando
também dependencias ciclicas.

Um design por valor, por outro lado, prima
pelo reasoning do código, aonde equality substitutability (ao contrário do
aliasing), facilita a construção e otimização de algoritmos sem necessidade
de se raciocinar sobre os *vários* compartilhamentos incidentais que ocorrem
num design OO. O polimorfismo dinâmico usado como detalhe de
implementação porém tem essa complexidade controlada, pois não se
espalha por todo design do projeto, neste caso é uma ótima forma de
de fazer type-erasure, por exemplo.

> --
> P.

[]'s

P.

unread,
Jan 29, 2013, 1:56:38 PM1/29/13
to ccppb...@googlegroups.com
Em terça-feira, 29 de janeiro de 2013 10h46min51s UTC-2, Thiago Adams escreveu:

On Jan 29, 10:05 am, "P." <pedro.lama...@gmail.com> wrote:
...
É uma ilusão esta imagem onde polimorfismo-dinâmico tem
> constrição pela classe base e polimorfismo-estático não tem constrição
> nenhuma, que polimorfismo-dinâmico é "complexo" e polimorfismo-estático é
> "simples".

Existe diferença. Citei o exemplo do draw, load, save.

Se  o motivo da criação da IControl 2 foi a Draw, então seria melhor
que se tivesse criado uma IDraw ao invés de colocar virtual Draw na
interface IControl.

Enfim, espero que fique claro que não é fácil fazer mudanças quando
existe heranças.


De modo algum isso está claro. A partir do momento que a nossa discussão permite um adaptador, a distância entre IControl e IControl2 pode ser fechada com um adaptador e ponto final. De modo algum está claro que escrever um adaptador polimórfico-de-runtime é mais difícil que escrever um adaptador polimórfico-estático. Este caso particular ou aquele -- como o algoritmo de soma indicado pelo Walter -- permitem selecionar a melhor técnica. Mas esta proposição de uma superioridade inconteste de uma técnica sobre a outra é falsa.

Jogando o jogo dos exemplos, considere um programa controlável remotamente por um canal de dados qualquer, por onde trafegam mensagens formatadas. Um analisador decide pela forma da mensagem qual é a ação que o programa deve tomar, de modo que a mensagem é um objeto polimórfico no modelo desse programa. Polimorfismo-estático é a melhor solução para expressar esse modelo? Não.

Mais: observe o modelo de configuração de alocador dos containeres C++. Como fazer variar o alocador em um programa? Substituindo um argumento de template. Agora, um programa onde uma decisão de configuração como essa -- qual é o alocador -- às vezes é tomada pela camada mais rasa do sistema. Esse é o cenário típico de "frameworks" usados por clientes que controlam coisas como o alocador. (Exemplo análogo: primitivas de sincronização de threads na openssl devem ser configuradas pelo usuário.) Como pode a camada mais rasa afundar o tipo do alocador através das camadas de abstração do sistema até o std::vector usado lá no fundo? (Como programar uma openssl onde o alocador de mutexes é um argumento de template?) Apenas tornando todas as camadas intermediárias em templates tal que possam propagar o tipo-argumento para a próxima camada. A aplicação dessa técnica exige que todo o sistema seja compilado em uma única tacada, impedindo o desacoplamento (!) no nível do dynamic loader. Maravilha.

--
 P.

Walter Mascarenhas

unread,
Jan 30, 2013, 4:29:49 AM1/30/13
to ccppb...@googlegroups.com

  Claro que há situações nas quais o poliformismo dinâmico é a melhor
(e mesmo a única) opção. Os exemplos do Pedro ilustram bem isso.

   Além disso, eu pelo menos não disse que templates são uma
maravilha metafísica. SFINAE por exemplo tem um cheiro
forte de gambiarra e C++ precisa evoluir para algo melhor
neste sentido, Outro exemplo são as mensagens de erro
absurdamente grandes e imprecisas, O tempo de compilação
então...

   O problema, na minha opinião, é o uso automático de
polimorfismo dinâmico, mesmo nas situações consideradas
pelo Felipe, nas quais passagem por valor levaria a código
melhor. No mais eu também uso polimorfismo dinâmico
quando me parece a melhor opção, e quem não fizer isto
que atire o primeiro template.

               walter.

Thiago Adams

unread,
Jan 30, 2013, 6:46:05 AM1/30/13
to ccppbrasil

Meu ponto inicial é que herança traz acoplamentos. Como o modelo
vtable do polimorfismo dinâmico é feito através de heranças então
carregaria consigo esta desvantagem. (ver primeira mensagem).

Não estava discutindo polimorfismo dinâmico versus estático que
parece ter se tornado o foco. O polimorfismo estático não precisa do
conceito de herança, ou seja, não apresenta a desvantagem que citei
sobre o polimorfismo dinâmico. Isso não significa que não existem
desvantagens do polimorfismo estático, ou que isso automaticamente
implique que ele seria melhor de maneira generalizada para qualquer
situação.

Se for este o foco, seria mais produtivo mostrar casos aonde é melhor
usar polimorfismo estático, e casos aonde é melhor usar polimorfismo
dinâmico ou casos aonde uma solução hibrida seja melhor.



On Jan 29, 4:56 pm, "P." <pedro.lama...@gmail.com> wrote:
> Em terça-feira, 29 de janeiro de 2013 10h46min51s UTC-2, Thiago Adams
> escreveu:
>
>
>
> > On Jan 29, 10:05 am, "P." <pedro.lama...@gmail.com> wrote:
> > ...
> > É uma ilusão esta imagem onde polimorfismo-dinâmico tem
> > > constrição pela classe base e polimorfismo-estático não tem constrição
> > > nenhuma, que polimorfismo-dinâmico é "complexo" e polimorfismo-estático
> > é
> > > "simples".
>
> > Existe diferença. Citei o exemplo do draw, load, save.
>
> Se  o motivo da criação da IControl 2 foi a Draw, então seria melhor
>
> > que se tivesse criado uma IDraw ao invés de colocar virtual Draw na
> > interface IControl.
>
> > Enfim, espero que fique claro que não é fácil fazer mudanças quando
> > existe heranças.
>
> De modo algum isso está claro. A partir do momento que a nossa discussão
> permite um adaptador, a distância entre IControl e IControl2 pode ser
> fechada com um adaptador e ponto final. De modo algum está claro que
> escrever um adaptador polimórfico-de-runtime é mais difícil que escrever um
> adaptador polimórfico-estático. Este caso particular ou aquele -- como o
> algoritmo de soma indicado pelo Walter -- permitem selecionar a melhor
> técnica. Mas esta proposição de uma superioridade inconteste de uma técnica
> sobre a outra é falsa.

Para evitar ficar num discussão mais abstrata, pretendo fazer um
exemplo mais completo (baseado na experiência real) usando dois
estilos e depois propor uma alteração (que ocorre na realidade também)
e comparar o número de mudanças que precisam ser feitas em cada um a
fim de ter uma ideia mais precisa sobre o acoplamento e dificuldade de
reuso.
De qualquer forma, sempre achei que era bastante claro para todos que
herança traz acoplamentos.

> Jogando o jogo dos exemplos, considere um programa controlável remotamente
> por um canal de dados qualquer, por onde trafegam mensagens formatadas. Um
> analisador decide pela forma da mensagem qual é a ação que o programa deve
> tomar, de modo que a mensagem é um objeto polimórfico no modelo desse
> programa. Polimorfismo-estático é a melhor solução para expressar esse
> modelo? Não.

Acredito que isso faça parte de uma discussão polimorfismo dinâmico
versus estático?
Ao meu ver, se você não tem uma cadeia de heranças, ou múltiplas
interfaces, ou se você simplesmente quer criar uma barreira entre
interface e implementação o polimorfismo via interfaces é uma solução
sem grandes problemas.

Também é possível, dependente do complexidade da mensagem, que está
adquira mais de um "conceito/interface" e isso acabe criando um
problema de acoplamento. Sem conhecer o problema não adianta falar de
forma genérica.

Thiago Adams

unread,
Feb 16, 2013, 7:36:11 AM2/16/13
to ccppbrasil

Achei o seguinte link que tem relação com o que foi falado aqui:

Open and Efficient Type Switch for C++
https://parasol.tamu.edu/~yuriys/pm/

Aqui tem um paper dos mesmos autores:
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3449.pdf

No site tem uma lib:

Este exemplo ajuda a entender a finalidade:

https://parasol.tamu.edu/~yuriys/pm/example01.html


Thiago Adams

unread,
Sep 10, 2013, 9:22:33 AM9/10/13
to ccppb...@googlegroups.com
Reply all
Reply to author
Forward
0 new messages