| FAQ Lite | ||||||||||
| Aprendendo C++ Se Você Já Conhece Smalltalk | ||||||||||
|
||||||||||
| [ 27.1 ] Qual é a diferença entre C++ e Smalltalk? |
Ambas suportam completamente o paradigma OO.
Nenhuma delas é categórica e universalmente melhor que a
outra. Mas há diferenças entre elas. As diferenças mais importantes são:
Nota: Alguns programadores C++ têm experiência anterior em Smalltalk. Se esse é o seu caso, essa seção vai lhe apresentar os tópicos mais importantes que você deve conhecer para fazer a transição. Por favor, não tente estabelecer qual das duas linguagens é inferior ou pior do que a outra, e não interprete essa seção como a apologia de uma ou de outra linguagem. (Eu não sou um fanático por uma linguagem específica, eu trabalho am ambos os comitês de padronização - ANSI C++ e ANSI Smalltalk). Essa seção visa ajudá-lo a entender e a lidar com as diferenças. |
| [ 27.2 ] O que é prototipação estática e como isso é semelhante/diferente de Smalltalk? |
| Prototipação estática determina ao
compilador que verifique estaticamente (em tempo de compilação) a compatibilidade de
tipos de dados em toda operação, ao invés de gerar código para fazer essa
verificação em tempo de execução. Por exemplo, com prototipação estática, a
compatibilidade de tipos para os argumentos de uma função é verificada em tempo de
compilação, não em tempo de execução. Uma incompatibilidade de tipos de dados, se
houver, é detectada como um erro pelo compilador, não pelo sistema de execução. Em código OO, a incompatibilidade de tipos mais comum é a que invoca uma função para um objeto que não está preparado para tratar a operação. Por exemplo, se class Fred tem uma função membro f() mas não tem g(), e fred é uma instância de class Fred, então fred.f() é uma chamada legal, mas fred.g() é ilegal. C++ identifica o erro em tempo de compilação, e Smalltalk identifica o erro em tempo de execução. Em termos técnicos, C++ é como Pascal - pseudo estaticamente prototipado - uma vez que pointer cast e uniões podem ser usadas para violar o sistema de prototipação, o que me faz lembrar: use pointer cast e uniões tão freqüentemente quanto você usaria goto) |
| [ 27.3 ] Qual é melhor para C++: prototipação estática ou dinâmica? |
| Para situar-se no contexto, por favor leia a FAQ anterior. Se você quer usar C++ em sua forma mais efetiva, use-o como uma linguagem de prototipação estática. C++ é flexível o bastante para que você possa (via pointer cast , uniões e macros #define) fazê-lo parecer-se com Smalltalk. Mas não faça isso. (Em tempo: evite o uso de #define.) Há situações em que o uso de pointer cast e de uniões são necessários e até indispensáveis, mas useo-os com extremo cuidado. Um pointer cast diz ao compilador para acreditar em você. Um pointer cast incorreto pode corromper o controle de memória, invadir memória pertencente a outros objetos, chamar funções inexistentes, e causar falhas gerais. Isso não é bom. Se você evita essas construções, você torna seu programa mais seguro e mais veloz, já que tudo que pode ser verificado em tempo de compilação é um trabalho a menos em tempo de execução. Se você estiver interessado em usar um pointer cast, use então o novo estilo de pointer cast. O exemplo mais comum é alterar o antigo estilo de pointer cast (X*)p para o novo estilo de conversão dinâmica dynamic_cast<X*>(p), onde p é um pointer e X é um tipo de objeto. Em adição ao dynamic_cast, há ainda static_cast e const_cast, mas dynamic_cast é um dos que simula a maior parte das vantagens da prototipação dinâmica (o outro é a construção typeid(), por exemplo typeid(*p).name() vai retornar o nome do tipo apontado por *p). |
| [ 27.4 ] Como você usa herança em C++? É diferente do uso em Smalltalk? |
| Algumas pessoas acreditam que a finalidade de
herança é a reutilização de código. Em C++ isso não é verdade. Definindo
claramente: herança não é um recurso para reutilização de código. A finalidade de herança em C++ é expressar a subordinação de interfaces (sub-tipificação), e não reusar código. Em C++ a reutilização de código é obtida via composição e não via herança. Em outras palavras, herança é muito mais uma técnica de especificação do que uma técnica de implementação. Essa é a principal diferença com Smalltalk, onde há uma única forma de herança (C++ fornece herança private para compartilhar o código mas não ajustar-se a interface, e herança public para tipo-de). A linguagem Smalltalk propriamente dita, permite que você tenha um efeito de ocultar um método herdado, através de uma sobreposição que chama um método "não entendido". Mais ainda, Smalltalk permite que um relacionamento conceitual "é-um" exista idenpendentemente da hierarquia de classes. Ou seja, subtipos não precisam ser subclasses, você pode fazer algumacoisa "é-um" Stack ainda que não seja derivado da class Stack. Em contraste, C++ é mais restritivo no que se refere a herança: não há como fazer um relacionamento conceitualmente é-um sem o uso de herança (o recurso do C++ mais próximo disso é a implementação de classes base abstratas (ABC), para separar interface de implementação). O compilador C++ explora a informação semântica associada a herança public para implementar prototipação estática. |
| [ 27.5 ] Quais as conseqüências práticas das diferenças de herança entre Smalltalk e C++? |
| Para situar-se no contexto, por favor leia a FAQ anterior. Smalltalk permite que você crie um subtipo que não é uma subclasse, e permite que você crie uma subclasse que não é um subtipo. Isso permite que programadores Smalltalk estejam bem à vontade no armazenamento de dados (bits, representação, estrutura de dados) dentro das classes. Por exemplo, você pode armazenar uma lista ligada em uma class Stack. ao final, se alguém quer uma Stack baseada em matriz, não precisa herdar de Stack, pode herdar de Array se quizer, mesmo que ArrayBasedStack não seja um tipo de Array. Em C++ você não pode ter tanta liberdade. Apenas mecanismos (código de funções membro), mas não representação (bits de dados) podem ser sobrepostos em subclasses. Eu gosto de pensar na diferença entre um ATV e um Masseratti. Um ATV (veículo para qualquer terreno) é mais divertido, já que você pode passear dirigindo por campos, trilhas, etc. Um Masseratti, por outro lado, leva você mais depressa mas o obriga a andar na estrada. Meu alerta aos programadores C++ é simples: fiquem na estrada. Mesmo que você seja uma dessas pessoas que gostam da liberdade de dirigir por trilhas rústicas, não faça isso em C++, não é uma boa medida. |
|
| | Home | Bookmarks | Universidades | Para Saber mais | Universidades | WEB Directory | Mapa do site | | |