Usando C ++, mas não usando os recursos específicos da linguagem, deve mudar para C?

16

Estou desenvolvendo um emulador de NES como um hobby, no meu tempo livre. Eu uso C ++ porque é a linguagem que eu uso principalmente, conheço e gosto principalmente.

Mas agora que avancei no projeto, percebo que não estou usando quase nenhum recurso específico do C ++ e poderia ter feito isso em C simples e obtendo o mesmo resultado. Não uso modelos, sobrecarga de operador, polimorfismo, herança. Então o que você diria? devo ficar em C ++ ou reescrevê-lo em C?

Não farei isso para obter ganho de desempenho, isso pode ter um efeito colateral, mas a idéia é por que devo usar C ++ se não precisar?

Os únicos recursos do C ++ que estou usando são as classes para encapsular dados e métodos, mas isso também pode ser feito com estruturas e funções, estou usando new e delete, mas também poderia usar malloc e free, e estou usando herança apenas para retornos de chamada, o que pode ser alcançado com ponteiros para funções.

Lembre-se de que é um projeto de hobby, não tenho prazos; portanto, o tempo e o trabalho extras que exigiriam uma reescrita não são um problema, também podem ser divertidos. Então, a pergunta é C ou C ++?

Petruza
fonte
3
Parece-me que você já respondeu a si mesmo: por que usar C ++ se você só precisa de C? Existem muitas situações em que C está perfeitamente bem.
Giorgio
3
@Giorgio: E todos eles evaporam após os primeiros sessenta segundos e você precisa manter seu código.
DeadMG
7
I use C++ because is the language I use mostly, know mostly and like mostly.E essa é a resposta para sua pergunta. Você só deve mudar o idioma no meio do projeto quando houver um problema que o seu idioma atual não consiga resolver. I don't use templates, operator overloading, polymorphism, inheritance.Seria muito mais valioso aprender e usar os conceitos do que mudar para C. Como esse é um projeto de hobby, por que não usar algumas coisas que você nunca usou antes? Você sempre pode iniciar outro projeto em C e aprender o idioma, mas para o seu projeto atual não faz sentido mudar.
precisa
4
Também não uso 100% de uma linguagem em todos os projetos que escrevo. Você conhece o C ++ da melhor maneira, pode encontrar boas razões para usar recursos para os quais você não encontrou antes. Você pode começar a tratar C ++ como um muito mais seguro C, uma vez que você começar a usar o material da biblioteca padrão e impulsionar as construções como std::shared_ptr, std::unique_ptr, boost::scoped_ptr, std::vector, std::deque, std::map, etc. Para as funções de retorno de chamada, olhar para o uso de functors, e em C ++ 11, você também pode começar a usar coisas como funções lambda.
Wkl
3
@Giorgio: Sim. A rolagem da lista vinculada de infinitos é obrigada a produzir erros desnecessários.
DeadMG

Respostas:

40

Você não está usando agora, mas da próxima vez que vazar memória ou obter uma dupla exclusão, você estará implorando para voltar std::vector<T>, std::unique_ptr<T, Del>e std::shared_ptr<T>, o que pode resolver esses problemas facilmente- quase trivialmente. É o que acontece com todos que usam C sobre C ++, eventualmente, e os mais inteligentes simplesmente não esperam que os erros apareçam antes de passarem.

O código que usa newe deletediretamente não pertence realmente ao C ++, ele pertence àquele tipo de meia casa que chamamos de "C com classes". É aí que a linguagem era por volta de 1985. Não é particularmente semelhante a C ++, por volta de 2011. Em toda a probabilidade, onde quer que você aprendeu C ++ simplesmente não ensiná-lo algo muito bem que é, infelizmente, em vez comum- e com uma educação melhor, você faria encontre o uso desses recursos.

Especificamente, como listei acima, as estruturas de dados genéricas do C ++ e as classes de gerenciamento de recursos são fundamentalmente muito superiores a tudo o que C tem a oferecer. Se você deseja uma matriz alocada dinamicamente, use std::vector<T>. Esse é um caso de uso bastante comum. Se você não os estiver usando, seu código corre um enorme risco de erro desnecessariamente, especialmente relacionado ao gerenciamento de recursos. O C ++ pode garantir a segurança e reutilizar o código de uma maneira que o C nunca possa tocar.

No entanto, acho que você também pode estar esperando demais. Escrever modelos e sobrecargas de operador não é comum para os consumidores da biblioteca. Se o seu código usar std::vector<T>, você não precisará escrever um modelo para que isso aconteça. Se seu código usa std::string, ninguém está forçando você a sobrecarregar seus operadores. Você só precisa fazer essas coisas para escrever std::vector<T> e std::string- mas ainda pode tirar proveito delas.

O polimorfismo / herança também possui apenas um caso de uso específico. Se o seu código não exigir que você escreva nenhum modelo ou use funções virtuais, ele não o fará, e existem programas ou segmentos de programas nos quais você não precisa escrever seus próprios modelos.

Além disso, não há ganho de desempenho em C sobre C ++.

DeadMG
fonte
1
@ Giorgio: make_sharedexiste, e você pode escrever um make_uniquemodelo trivial que faz o mesmo trabalho. É mais seguro.
precisa saber é o seguinte
4
Ótima resposta. Prego na cabeça. O C ++ é mais valioso para essas pequenas bibliotecas que sempre devemos usar.
Andres Jaan Tack (
2
@ Giorgio: É inseguro, porque ao chamar vários argumentos como esse, você pode obter um vazamento de memória no caso de exceção, e make_sharedé mais eficiente. Somente as funções de fábrica podem oferecer segurança de exceção garantida.
DeadMG
6
@ tp1: WTF? Em inglês por favor.
DeadMG
2
@ Lohoris Você não precisa de uma citação para o senso comum. De que maneira C deve ter mais desempenho que C ++?
Chris diz Reinstate Monica
7

Mesmo se você não usar recursos específicos do C ++, um compilador C ++ detectará mais problemas do que um C devido ao sistema de tipo mais estrito do C ++.

Nemanja Trifunovic
fonte
6

Eu olhava para isso de outra direção. Você ganhará algo reescrevendo o código em C? Mesmo em um projeto puramente hobby, há um custo associado a uma reescrita como essa. Se nada mais existir, suponho que seria chamado de custo de oportunidade - ou seja, as outras coisas que você poderia ter feito naquele tempo se não estivesse perdendo tempo reescrevendo-o em C.

Conclusão: a menos que você ache que o código provavelmente será usado em algum ambiente em que o acesso ao C ++ seja realmente limitado (ou inexistente), seria uma perda de tempo inútil, na melhor das hipóteses. Pelo menos na minha experiência, isso geralmente vai muito além disso muito rapidamente - pensando no código que eu escrevi em C ++ que tinha que ser convertido em C, eu me lembro claramente que mesmo em alguns casos em que parecia deveria ser trivial, eu estava usando muito mais recursos específicos para C ++ do que eu percebi inicialmente. Para ter muita esperança de ser útil, você precisa segmentar o C89 / 90, caso em que você rapidamente se lembra de coisas como ter que definir todas as variáveis ​​no início de um bloco, em vez de onde elas realmente estão. usava.

Em resumo, a menos que você tenha certeza de que a reescrita em C trará um benefício real, há quase inevitavelmente coisas muito melhores para fazer.

Jerry Coffin
fonte
+1 Algum tempo atrás, eu tive que escrever uma biblioteca para ser usada em outro projeto C e achei que era uma boa ideia implementá-la também em C, cara que idiota eu era naquela época.
Chris diz Reinstate Monica
1

Como resposta mais geral:

Não mude para C ++ apenas porque você está usando alguns dos seus recursos mais exclusivos. Um dia, você pode precisar desses recursos e vai bater na cabeça porque está usando C.

Dinâmico
fonte
1

Para o desenvolvimento hobby, eu consideraria voltar às linguagens simples C. C e C têm mais probabilidade de serem suportadas em pequenos módulos de desenvolvimento hobby.

Muitas das respostas aqui podem ser de tipos profissionais de software. Como um hobby, você não estará codificando continuamente ou em período integral. Portanto, considere em qual idioma você provavelmente se lembrará ou esquecerá as peculiaridades, se você apresentar seu projeto por um ano e depois voltar e tentar ler seu código depois de ficar enferrujado na codificação. O C ++, com um conjunto de recursos mais rico, pode levar mais ou menos tempo para readquirir, dependendo do seu estilo de codificação.

hotpaw2
fonte
1

Não é fácil responder às suas perguntas, pois não sabemos se você está trabalhando no projeto para aprimorar suas habilidades específicas de linguagem (C vs C ++) ou para aprimorar outras habilidades de programação (design, resolução de problemas etc.).

"Os únicos recursos do C ++ que estou usando são as classes para encapsular dados e métodos, mas isso também pode ser feito com estruturas e funções". Isso não é verdade. structsem C não suporta encapsulamento e não pode conter funções (métodos) - pelo menos não sem o uso de técnicas como ponteiros para funções. Além disso, as funções em C são mais fracas porque não podem ser sobrecarregadas.

"Estou usando new e delete, mas também posso usar malloc e free, e estou usando herança apenas para retornos de chamada, o que pode ser alcançado com ponteiros para funções". Como deadmg mencionado, o uso direto newe deleteem C ++ não é incentivado. Além disso, a herança IMHO (e o GoF) na POO deve ser preferida à composição apenas quando o polimorfismo é necessário. E não acho que seja trivial obter polimorfismo (ligação tardia) em C usando ponteiros para funções.

Fora isso, não tentarei convencê-lo de que C ++ é "melhor" que C porque é uma questão de preferência e sempre depende do problema que você está tentando resolver (o uso de recursos OOP para desenvolver seu emulador NES pode ser uma boa ideia).

sakisk
fonte
1
structsde fato, em C pode ser usado para encapsular métodos. Você simplesmente cria uma estrutura de ponteiros de função e inicializa-os para apontar para as funções que desejar. Veja lxr.linux.no/linux+v3.3/include/linux/fs.h#L1598 para obter um exemplo.
Robert Martin
Está certo. Obrigado pelo comentário, estendi a resposta.
Sakisk
Agradável. Mais um nit: funções em C podem ser sobrecarregadas (pense printf), mas, ao fazer isso, você perde qualquer verificação de tipo. Não há como ter um conjunto finito de declarações aceitáveis: é 1 (e você obtém a verificação de tipo) ou "muitos" (e perde toda a verificação de tipo, com grande risco pessoal). Como na maioria das coisas em C, é possível, mas geralmente desconfortável.
Robert Martin
Ponteiros para funções são uma técnica C avançada? Verdade?
Donal Fellows
@DonalFellows Você está certo, eu exagerei. Removido avançado ... :)
sakisk
0

Eu sou muito iniciante, então aqui estão meus 2 bits.

Estou aprendendo C e C ++ no Wibit.net com alguns bons tutoriais básicos em vídeo, talvez eles possam ajudar muito a ter uma visão geral da "situação" (não um anúncio!)

Eu aconselho você a mudar para C, apenas para aprender, como você é um hobby, isso será um prazer, não um problema.

Eu aconselho mais. Faça nos dois idiomas. Compare a maneira e as soluções que você encontrará e usará. Tenho certeza de que não será "tão fácil" como você espera ... mas com certeza você aprenderá muito!

H_7
fonte
1
Muito obrigado, mas não estou aprendendo, eu já conheço C e C ++, estou perguntando qual usar para esse projeto específico.
Petruza
Opa, minha hora de aprender! = P
H_7
1
Além disso, aconselho que, em vez de tutoriais em vídeo, você obtenha os livros de Kernigan e Stroustrup, um bom IDE (Visual Studio, Eclipse, Xcode) e aprenda codificando os exemplos, tentativa e erro e recorrendo ao stackoverflow.
Petruza
-1

Aqui estão os prós e contras de C ++ vs. C:

  1. Mover para C tornaria mais fácil permanecer dentro do subconjunto C ++ escolhido, porque o compilador causaria erro quando você sair dele. Se o principal problema é permanecer dentro do subconjunto decidido, essa alternativa deve ser escolhida. (por que não temos suporte de compilador para isso?)
  2. Uma vez que você possa permanecer dentro do subconjunto de recursos c ++ escolhido, o próximo passo é tentar alterar o subconjunto para se livrar de convenções ruins que quebram o código. Isso requer o uso de c ++ inteiro.
  3. Depois de ter "permanecido dentro do subconjunto" e "é um bom subconjunto", saia dos recursos do c ++ e comece a pensar nos requisitos.
tp1
fonte