Estou tentando entender a diferença entre linguagens procedurais como C e linguagens orientadas a objetos como C ++. Eu nunca usei C ++, mas tenho discutido com meus amigos sobre como diferenciar os dois.
Foi-me dito que o C ++ possui conceitos orientados a objetos, bem como modos público e privado para definição de variáveis: coisas que o C não possui. Eu nunca tive que usá-los enquanto desenvolvia programas no Visual Basic.NET: quais são os benefícios deles?
Também me disseram que se uma variável é pública, pode ser acessada em qualquer lugar, mas não está claro como isso é diferente de uma variável global em um idioma como C. Também não está claro como uma variável privada difere de uma variável local.
Outra coisa que ouvi é que, por motivos de segurança, se uma função precisar ser acessada, ela deverá ser herdada primeiro. O caso de uso é que um administrador deve ter apenas os direitos necessários e não tudo, mas parece que uma condicional funcionaria também:
if ( login == "admin") {
// invoke the function
}
Por que isso não é ideal?
Dado que parece haver uma maneira processual de fazer tudo orientado a objetos, por que devo me preocupar com programação orientada a objetos?
fonte
Respostas:
Até agora, todas as respostas se concentraram no tópico de sua pergunta, que é "qual é a diferença entre c e c ++". Na realidade, parece que você sabe o que é diferença, mas simplesmente não entende por que precisaria dessa diferença. Então, outras respostas tentaram explicar OO e encapsulamento.
Queria entrar em contato com mais uma resposta, porque, com base nos detalhes da sua pergunta, acredito que você precisa dar vários passos para trás.
Você não entende o propósito de C ++ ou OO, porque para você, parece que seu aplicativo simplesmente precisa armazenar dados. Esses dados são armazenados em variáveis. "Por que eu gostaria de tornar uma variável inacessível? Agora não consigo mais acessá-la! Ao tornar tudo público, ou melhor ainda, global, posso ler dados de qualquer lugar e não há problemas." - E você está certo, com base na escala dos projetos que está escrevendo atualmente, provavelmente não existem muitos problemas (ou existem, mas você ainda não os percebeu).
Acho que a pergunta fundamental que você realmente precisa responder é: "Por que eu iria querer ocultar dados? Se faço isso, não posso trabalhar com eles!" E é por isso que:
Digamos que você inicie um novo projeto, abra seu editor de texto e comece a escrever funções. Toda vez que você precisa armazenar algo (para lembrá-lo mais tarde), você cria uma variável. Para simplificar, você torna suas variáveis globais. Sua primeira versão do seu aplicativo é ótima. Agora você começa a adicionar mais recursos. Você tem mais funções, alguns dados armazenados antes precisam ser lidos em seu novo código. Outras variáveis precisam ser modificadas. Você continua escrevendo mais funções. O que você pode ter notado (ou, se não, absolutamente notará no futuro) é que, à medida que seu código aumenta, você leva mais e mais tempo para adicionar o próximo recurso. E à medida que seu código aumenta, fica cada vez mais difícil adicionar recursos sem interromper algo que costumava funcionar. Por quê? Porque você precisa lembrar o que todossuas variáveis globais estão armazenando e você precisa se lembrar de onde todas elas estão sendo modificadas. E você precisa se lembrar de qual função é adequada chamar em que ordem exata e, se você chamá-las em uma ordem diferente , poderá receber erros porque suas variáveis globais ainda não são válidas. Você já se deparou com isso?
Qual o tamanho dos seus projetos típicos (linhas de código)? Agora, crie um projeto de 5000 a 50000 vezes maior que o seu. Além disso, existem várias pessoas trabalhando nele. Como todos na equipe podem se lembrar (ou mesmo estar cientes) do que todas essas variáveis estão fazendo?
O que eu descrevi acima é um exemplo de código perfeitamente acoplado. E desde o início dos tempos (supondo que o tempo tenha começado em 1º de janeiro de 1970), a humanidade tem procurado maneiras de evitar esses problemas. A maneira de evitá-los é dividindo seu código em sistemas, subsistemas e componentes e limitando quantas funções têm acesso a qualquer parte dos dados. Se eu tiver 5 números inteiros e uma string que represente algum tipo de estado, seria mais fácil trabalhar com esse estado se apenas 5 funções configurassem / obtivessem os valores? ou se 100 funções definem / obtêm esses mesmos valores? Mesmo sem as linguagens OO (isto é, C), as pessoas têm trabalhado duro para isolar dados de outros dados e criar limites de separação limpos entre diferentes partes do código. Quando o projeto chega a um determinado tamanho, a facilidade de programação não é ", posso acessar a variável X da função Y",
É por isso que os conceitos de OO foram introduzidos e é por isso que eles são tão poderosos. Eles permitem que você esconda seus dados de si mesmo e você deseja fazê-lo de propósito, porque quanto menos código visualizar esses dados, menor a chance de que, ao adicionar o próximo recurso, você quebre alguma coisa. Esse é o principal objetivo dos conceitos de encapsulamento e programação OO. Eles permitem que você divida nossos sistemas / subsistemas em caixas ainda mais granulares, a um ponto em que, não importa quão grande seja o projeto geral, um determinado conjunto de variáveis só pode ser acessado por 50-200 linhas de código e pronto! Obviamente, há muito mais na programação OO, mas, em essência, é por isso que o C ++ oferece opções de declaração de dados / funções como privada, protegida ou pública.
A segunda maior idéia em OO é o conceito de camadas de abstração. Embora as linguagens procedurais também possam ter abstrações, em C, um programador deve fazer um esforço consciente para criar essas camadas, mas em C ++, quando você declara uma classe, você cria automaticamente uma camada de abstração (ainda é sua decisão se essa abstração é ou não adicionará ou removerá valor). Você deve ler / pesquisar mais sobre as camadas de abstração e, se tiver mais perguntas, tenho certeza de que este fórum ficará mais do que feliz em respondê-las.
fonte
Hmm ... talvez seja melhor fazer backup e tentar dar uma idéia da intenção básica da programação orientada a objetos. Grande parte da intenção da programação orientada a objetos é permitir a criação de tipos de dados abstratos. Para um exemplo realmente simples com o qual você sem dúvida está familiarizado, considere uma string. Uma string normalmente possui um buffer para armazenar o conteúdo da string, algumas funções que podem operar na string (pesquisar nela, acessar partes dela, criar substrings, etc.) Também terá (pelo menos normalmente) algo para acompanhe o comprimento (atual) da string e (provavelmente) o tamanho do buffer; se (por exemplo) você aumentar o tamanho da string de 1 para 1000000, ele saberá quando precisa de mais memória para armazenar a maior conteúdo.
Essas variáveis (buffer, comprimento atual e o tamanho do buffer) são privados para a própria corda, mas eles são não local para uma função particular. Cada string possui conteúdo de algum comprimento específico, portanto, precisamos rastrear esse conteúdo / comprimento para essa string. Por outro lado, a mesma função (por exemplo, para extrair uma subcadeia de caracteres) pode operar em várias seqüências diferentes em momentos diferentes, para que os dados não possam ser locais para a função individual.
Como tal, acabamos com alguns dados que são privados da string, portanto, são acessíveis (diretamente) apenas às funções da string. O mundo externo pode obter o comprimento da cadeia usando uma função de cadeia, mas não precisa saber nada sobre as partes internas da cadeia para obtê-lo. Da mesma forma, ele pode modificar a string - mas, novamente, faz isso através das funções da string, e somente elas modificam diretamente essas variáveis locais no objeto string.
Tanto quanto a segurança vai, eu notar que, enquanto isso é razoável como uma analogia, é não como as coisas realmente funcionam. Em particular, o acesso em C ++ não se destina especificamente a atender ao mesmo tipo de requisitos que o acesso em um sistema operacional. Um sistema operacional deve aplicar as restrições para que (por exemplo) um usuário normal não possa fazer coisas reservadas para um administrador. Por outro lado, o controle de acesso em C ++ destina-se apenas a evitar acidentes. Por design, quem quiser pode ignorá-los facilmente. Eles estão na mesma ordem em que marcam um arquivo como somente leitura, para que você não o exclua acidentalmente. Se você decidir excluir o arquivo, é trivial alterá-lo de somente leitura para leitura e gravação; tudo o que é definido como somente leitura é fazer você pensar um pouco e decidir excluir o arquivo para que ele não seja excluído por acidente, apenas pressionando a tecla errada na hora errada.
fonte
OOP versus C não é sobre nada do que você discutiu. Trata-se principalmente de empacotar código em áreas que não afetam / não podem (não intencionalmente (ou às vezes até intencionalmente)).
C permite basicamente executar qualquer função de qualquer lugar. OOP evita isso agrupando métodos em classes e permitindo apenas o uso dos métodos fazendo referência à classe que os contém. Portanto, uma grande vantagem potencial do OOP é que é muito mais provável que você tenha um melhor arranjo de código sem muita experiência para lhe dizer que deveria.
fonte
Uma classe bem escrita deve ser uma pequena "ilha de confiança": você pode usá-la e assumir que faz "a coisa certa" e que o protege de armadilhas comuns. Isso torna uma boa classe um bloco de construção, que é muito mais reutilizável como um monte de funções e variáveis, que podem funcionar bem, mas mostram todas as suas entranhas feias e forçam você a entender como elas funcionam juntas, como precisam ser inicializadas etc. Uma boa classe deve ser como um plugue USB, enquanto a solução processual é como um monte de fios, chips, estanho e um pouco de solda.
Um ponto que não foi discutido em profundidade é o aspecto da interface / implementação. Uma interface descreve o comportamento, mas não a realização. Portanto, uma interface de lista descreve o conceitode uma lista e seu comportamento: você esperaria coisas como adicionar, remover e dimensionar métodos. Agora, existem muitas maneiras diferentes de implementar esta lista, por exemplo, como uma lista vinculada ou usando um buffer de matriz. O poder da programação OO é que, usando uma interface, você pode raciocinar sobre o comportamento sem conhecer a implementação. O acesso a variáveis ou métodos internos destruiria essa abstração, você não poderia substituir uma implementação de lista por outra e não poderia melhorar uma implementação existente sem tocar no código usando a classe Essa é uma das principais razões pelas quais variáveis e métodos privados são necessários: Para proteger detalhes internos da implementação, para que a abstração permaneça intacta.
OO vai um passo além: por exemplo, para bibliotecas, você pode definir uma interface para coisas que ainda não existem e escrever um código que funcione com essa interface. Os usuários podem escrever classes implementando a interface e usar os serviços fornecidos pela biblioteca. Isso permite um grau de flexibilidade que não é possível com a programação procedural.
fonte
SetLocation
pode ser usado para mover aMonster
, enquantoSetPosition
pode mover aPopupWindow
eMove
pode ser usado para ajustar a posição de aDisplayCursor
). Tentando encontrar o método "mover" certo ... #MyMonstor->
o editor mostra apenas uma lista de métodos aplicáveis a itens do tipoMonster
. Se houver muitas dezenas de tipos diferentes de coisas, cada uma suportando cerca de uma dúzia de operações, reduzir a quantidade de lixo nas listas de métodos em 90% pode facilitar bastante a produtividade.it
do tipoSuperFancyWhizBang
, invocar um dosSuperFancyWhizBang
métodos de onit
não exige a gravação do tipoSuperFancyWhizBang
; dizendoit.woozle()
direcionará o compilador a procurar automaticamentewoozle
dentro deleSuperFancyWhizBang
.Existe uma maneira de fazer tudo com uma máquina de Turing ou, no mínimo, em uma linguagem assembly para o código da máquina que um programa C ou C ++ eventualmente compilará.
Portanto, a diferença não está no que o código pode fazer, mas no que as pessoas podem fazer.
Pessoas cometem erros. Grande quantidade.
OOP apresenta um paradigma e uma sintaxe que ajuda a reduzir o tamanho e a densidade de probabilidade do espaço de possíveis erros de codificação humana. Às vezes, tornando o erro ilegal para uma determinada classe de objeto de dados (como não é um método declarado para esse objeto). Às vezes, tornando o erro mais detalhado ou com aparência estilística, em comparação ao uso canônico da linguagem. Às vezes, exigindo uma interface com muito menos usos possíveis inconsistentes ou emaranhados (público vs. privado). etc.
Quanto maior o projeto, maior a probabilidade de erros. O qual um novo codificador pode não ser exposto se tiver experiência com programas pequenos. Daí a potencial confusão de por que o POO é valioso.
fonte
Sua pergunta parece mais sobre o objetivo do POO do que sobre a diferença. O conceito em sua postagem é Encapsulamento; e existe um encapsulamento para oferecer suporte a CHANGE. Quando outras classes acessam seus internos, fica difícil modificá-los sem quebrá-los. No OOP, você fornece uma interface (membros públicos) por meio da qual você permite que outras classes interajam com as suas e oculta seus internos para que eles possam ser alterados com segurança.
fonte
Espero que você nunca queira mais de uma string no seu aplicativo. Espero também que suas variáveis locais persistam entre as chamadas de função. Essas coisas podem ser as mesmas em termos de acessibilidade, mas em termos de vida útil e outros usos? Eles não são absolutamente iguais.
fonte
Como muitos disseram que qualquer programa, uma vez compilado, é transformado em um código binário e, como uma string binária pode ser usada para representar um número inteiro, qualquer programa é eventualmente apenas um número. Entretanto, definir o número necessário pode ser bastante difícil e é por isso que as linguagens de programação de alto nível surgiram. Linguagens de programação são apenas modelos do código de montagem que eventualmente produzem. Gostaria de explicar a diferença entre programação procedural e OO por meio deste artigo muito agradável sobre Programação Orientada a Contexto http://www.jot.fm/issues/issue_2008_03/article4/
Como você pode ver nesta figura, mostrada no artigo, a programação procedural fornece apenas uma dimensão para associar uma unidade computacional a um nome. Aqui, chamadas ou nomes de procedimentos são mapeados diretamente para implementações de procedimentos. Na Figura-a chamada m1 não deixa escolha, a não ser a invocação da única implementação do procedimento m1.
A programação orientada a objetos adiciona outra dimensão para a resolução de nomes à programação processual. Além do nome do método ou procedimento, o envio de mensagens leva em consideração o destinatário da mensagem ao procurar um método. Na Figura-b, vemos duas implementações do método m1. A seleção do método apropriado depende não apenas do nome da mensagem m1, mas também do receptor da mensagem real, aqui Ry.
Isso de fato permite encapsulamento e modularização.
A Figura-c é finalmente sobre programação orientada a assuntos, estende o envio de métodos orientados a objetos por mais uma dimensão.
Espero que isso tenha ajudado você a pensar no POO de uma perspectiva diferente.
fonte
(+1) Fazer uma pergunta sobre algo que você não entende, é bom, mesmo que pareça bobagem.
A diferença é a programação orientada a objetos e classes. "Plain C", trabalha com dados e funções. "C ++" adiciona conceitos de "objeto e classes", além de vários conceitos secundários relacionados.
No entanto, defendo que os desenvolvedores aprendam "Plain C" antes de "C ++". Ou "Procedcal Pascal" antes de "Object Pascal".
Muitos desenvolvedores acham que os alunos devem ensinar apenas uma coisa.
Por exemplo, professores antigos que não recebem OO e ensinam apenas "C Estruturado Simples".
Ou professores "hipster" que ensinam apenas OO, mas não "C simples", porque "você não precisa". Ou ambos, sem se importar com a ordem de ensino.
Eu prefiro pensar que os alunos devem aprender o "Structured Plain C" e "Object Oriented C (C ++)". Com "Plain C", primeiro e "C ++", mais tarde.
No mundo real, você precisa aprender os dois paradigmas (além de outros paradigmas, como "funcional").
Pensar em programas estruturados como um "objeto" grande e único pode ajudar.
Você também deve enfatizar os namespaces ("módulos"), em ambos os idiomas, muitos professores simplesmente ignoram, mas isso é importante.
fonte
foo()
no C ++, pode ser uma função global, uma função no espaço para nome atual, uma função no espaço para nome que você usausing
, um método, um método herdado e se estiver na chamada de função: pode estar em um espaço para nome que pode ser resolvido por meio de pesquisa de nome baseada em argumento e o mesmo ocorre com Java e C #. Em C, pode ser apenas uma função estática no arquivo de origem atual ou uma de um cabeçalho.Em uma palavra, gerenciamento de projetos. O que quero dizer é que o C ++ me ajuda a impor regras de como meu código é usado por outras pessoas. Trabalhando em um projeto de 5,5 milhões de linhas, acho a programação orientada a objetos muito útil. Outra vantagem é o compilador que me leva (e a todos os demais) a seguir certas regras e detectar pequenos erros no tempo de compilação. Todas as vantagens teóricas também existem, mas eu só queria me concentrar nas coisas práticas diárias. Afinal, tudo é compilado no código da máquina.
fonte
Programação Orientada a Objetos é Programação Procedimental, com caixas.
No PP, você tem uma caixa, um estado, que se torna incrivelmente grande à medida que o projeto cresce, causando efeitos colaterais a cada vez que você esquece um pouquinho desse grande estado.
No OO, você tem muitas caixas, muitos estados e, à medida que o projeto cresce, as caixas crescem um pouco e o número de caixas cresce muito.
Continua sendo mais fácil olhar para caixas menores, fácil ter a ilusão de uma imagem inteira, mas na verdade quase impossível, pois olhar para classes e interfaces oculta os detalhes da implementação que podem ter importantes ramificações.
Na programação funcional, você tem muitas caixas de funções e decide que todas as funções têm uma entrada (parâmetros) e uma saída (retornos), com estritamente nenhum outro acesso ao contexto externo.
Como não há estado nem efeitos colaterais (por design), você pode analisar com segurança qualquer função separadamente do todo e saber 100% de como ela se comportará em qualquer circunstância.
Como você está encaixotando código por unidades lógicas que representam ações, também é possível ter apenas uma caixa por ação típica.
Isso reduzirá o código de qualquer projeto de grande escala em um fator enorme em comparação com o OOP, que promove ocultar várias funções analógicas em todo o código em diferentes classes.
Isso também superará muito o PP, porque você pode expandir o projeto por muito mais tempo, pois não há mais estado XXXXXXXL para acompanhar.
Em resumo, o PP é provavelmente a maneira mais simples de abordar um programa simples e o FP é provavelmente a maneira mais simples de abordar um programa complexo.
Se você considerar o objetivo de unificar todas as bases de código e melhorar a reutilização de código, o FP deve sempre ser usado, pois é o único paradigma que faz sentido em uma escala muito grande, bem como o único paradigma que possui 100% de reutilização (você pode basta copiar e colar uma função e usá-la em outro lugar, sem custos adicionais).
E você obtém testes de unidade 100% confiáveis gratuitamente.
E você não precisa escrever "final estático privado de_doom genius awesome string_1".
E você obtém paralelismo de graça.
fonte
A diferença de uma frase simples é que C ++ é C. com Classes. (Embora seja muito mais agora) Não sei por que você não quer aprender as diferenças entre dois lendo um ótimo artigo sobre C ++ na Wikipedia .... .Este artigo irá ajudá-lo bastante: - C ++ (Wikipedia)
Também pesquisar no assunto ajudará. Pedir que pessoas aleatórias expliquem isso pode ser complicado. IMHO, entende-se melhor lendo do que perguntando a alguém
fonte