É um bom hábito usar expressões C no código C ++?

19

Na escola, começamos a aprender C este ano, apesar do fato de estar muito adiantado na aula, e aprendi Java, C ++ e C enquanto a turma está na base de C. De qualquer forma, tenho me documentado, lido livros, artigos, e perguntei à minha professora por que eu deveria aprender C, e ela disse que era a base do C ++. Quando iniciei a programação, achei o C ++ muito mais fácil, mais tarde aprendi C. Mas nos livros você pode ver que o código C funciona em C ++, mas não é vice-versa.

Minha pergunta é bem direta ~ É um bom hábito usar expressões C em C ++? Deixe-me lhe dar um exemplo:

Este código deve

#include <stdio.h>
#include <iostream>

int main() {
int x;
scanf("%d", &x);
cout << "The number you entered is " << x << "And it's double is " << x*x;
return 0;
}

Seja mais eficiente ou melhor do que isso:

#include <iostream>

int main() {
int x;
cin >> x;
cout << "The number you entered is " << x << "And it's double is " << x*x;
return 0;
}

Eu já fiz uma documentação fácil sobre isso em alguns livros antigos e empoeirados, e pelo que pude encontrar, usar scanf em vez de cout também libera o fluxo ou algo assim, então estou basicamente perguntando se é melhor usar scanf e quais contextos.

Isso também se aplica ao arquivo IO, pois sempre achei o FI IO mais fácil em C do que em C ++. Esta pergunta vale para praticamente todas as expressões gerais em C aplicadas ao C ++. Também é notável que estou usando um compilador moderno e, no entanto, isso não deve importar, pois estou perguntando se é um bom hábito de programação usar expressões C no código C ++.

Provavelmente existem contras e vantagens em fazer isso, mas só estou procurando um tipo de resposta sim / por que não / por que.

Além disso, se houver algum detalhe que eu deixei de fora, poste um comentário.

Bugster
fonte
12
Tenha muito cuidado com a mistura stdioe iostream. Há uma certa ordem e sincronização garantida dentro de uma família que não se aplica necessariamente fora dela.
David Thornley
Obrigado pela dica, mas esse recado de código foi um exemplo puro. Obrigado mesmo assim.
Bugster
25
Se você está aprendendo programação; Você deve aprender o recuo apropriado!
bitmask
5
scanf () não é um ótimo exemplo; é tão propenso a erros de usar que eu aconselho você a evitá-lo em C ou C ++.
Russell Borogove
1
Pode ter sido apenas um exemplo de código, mas o comentário de David realmente chega ao cerne da questão por que você não deve usar expressões em C ao programar em C ++. Eles são idiomas completamente diferentes; não os confunda mais do que confunde Java e C, ou C ++ e Visual Basic.
Cody Gray

Respostas:

36

Não, é um mau hábito. Quando você faz isso para ganhar a vida, provavelmente acabará violando os guias de estilo aos quais sua equipe segue (ou pelo menos será atingido durante as revisões de código).

Sim, funciona, mas se houver um equivalente em c ++, use-o. (por exemplo, não tentar misturar printfscom couts)

jglouie
fonte
+1 - Curto e direto ao ponto. E isso destaca o ponto principal na minha resposta de que as diretrizes da equipe ajudam a unir as pessoas e unificá-las para que elas possam trabalhar juntas.
jmort253
Esse comentário responde muito bem à minha pergunta e traz um argumento sólido. Obrigado.
Bugster
1
@ThePlan thanks. todos tiveram ótimas respostas para essa pergunta.
Jglouie
1
Nota: o uso printfconsistente funcionará tão bem quanto o uso coutconsistente. Os únicos problemas são misturá-los e estilo.
user253751
Você pode dar um exemplo de um recurso em C que não possui um equivalente em C ++?
klutt
20

Em geral, C e C ++ são vistos como se fossem duas linguagens completamente separadas. Portanto, pode ser considerado uma forma incorreta usar a sintaxe C em um programa C ++.

Você está certo; no entanto, esse código C irá compilar muito bem. Realmente depende de quão flexível sua empresa é em termos de seguir os padrões. Se alguma vez eu fizesse a pergunta em uma entrevista, informaria que o entrevistador sabe que C funciona em C ++, mas também que C e C ++ são duas linguagens separadas e provavelmente não devem ser misturadas, a menos que haja muito, muito boa razão para fazê-lo.

Outra coisa a considerar é que os padrões ajudam a criar uma plataforma na qual mais pessoas podem trabalhar facilmente com o código. Embora você tenha tido sorte de ter um professor que o incentivou a aprender C, nem todos podem ter a mesma sorte. Portanto, misturar C em um programa C ++ pode ser confuso para alguém que nunca aprendeu C.

Em resumo, apenas porque você pode fazer algo não significa que você deve, e apenas porque você não deve fazer algo não significa que você não pode :)

jmort253
fonte
Entendo. E quanto à funcionalidade, existem casos específicos em que a sintaxe C é melhor que a sintaxe C ++?
Bugster
10

O C ++ é compatível com versões anteriores do C por design; portanto, normalmente o código C será compilado pelo compilador C ++ muito bem ( geralmente porque existem palavras reservadas adicionais em C ++ que não estão em C e podem ser usadas no código C que quebra a compilação).

No entanto, eu considero isso uma má prática misturar código. Se você usar scanf- use printf, se você estiver usando operator >>- use operator <<. A razão é que os operadores C ++ sobrecarregados podem encapsular a funcionalidade que você não conhece, e a incompatibilidade deles fará com que o programa faça coisas que você não queria.

Não há motivo específico para preferir a sintaxe C no código C ++, essas são linguagens diferentes e, ao usar a sintaxe C no código C ++ - você ainda está escrevendo o código C ++ , mas não usando muitas de suas ferramentas poderosas.

littleadv
fonte
5
A incompatibilidade entre C e C ++ é mais do que apenas palavras-chave. O sistema de digitação é alterado e há recursos existentes em C (especialmente C99), que não existem em C ++. (Por exemplo, matrizes de comprimento variável).
Arafangion
9

Se deixarmos de lado o estilo de codificação e os problemas estéticos, também existem vários problemas técnicos que você enfrenta ao usar C no código C ++:

  • O que é C? C90, C99 ou C11? Pode haver vários problemas de compatibilidade, dependendo do padrão C que você está usando. Tipo booleano, // comentários, recursos C99 como VLAs, inicializadores designados etc.

  • O C ++ possui uma digitação mais rigorosa que o C. Para compilar o código C no C ++, você provavelmente deve adicionar várias previsões de tipografia para obter o tipo esperado. Isso significa que você pode precisar reescrever o código C perfeitamente fino e com qualidade de produção para fazê-lo funcionar em C ++.

  • As previsões tipográficas aplicadas por uma digitação mais rígida geralmente são apenas uma coisa boa, mas em alguns casos elas podem introduzir ou ocultar bugs. Tome o exemplo infame do resultado de malloc () como exemplo. Isso deve ser tipificado em C ++, mas nunca em C. (1)

  • A mistura da funcionalidade C e C ++ pode levar a erros e comportamento indefinido. Por exemplo, não funcionará para alocar com malloc () e liberar com exclusão . 2)

  • Problemas de segurança de thread. A biblioteca padrão C não é segura para threads. A biblioteca C ++ padrão pode ou não ser segura para threads, se for o caso, adicionar chamadas de função da biblioteca C ao seu código destruirá isso.

    Como nota explicativa para programadores do Windows: o compilador Visual C ++ teve um bug de vazamento por algum tempo, quando a função CreateThread () da API do Windows foi usada no mesmo programa que a biblioteca C. (3, 4)

  • A convenção de chamada pode ser um problema em alguns compiladores, forçando um a usar extern "C"para dizer explicitamente quais funções devem ser vinculadas à "convenção de chamada C".

  • Detalhes irritantes. O operador de vírgula se comporta de maneira diferente. A vírgula à direita nas declarações struct / enum é permitida no C99 / C11, mas não no C ++. O escopo de vários tipos de variáveis ​​e funções são tratados de maneira diferente. Etc etc.

Provavelmente há ainda mais casos.


Referências:

  1. http://c-faq.com/malloc/cast.html
  2. http://www.parashift.com/c++-faq-lite/freestore-mgmt.html#faq-16.3
  3. http://www.flounder.com/badprogram.htm#CreateThread
  4. http://msdn.microsoft.com/en-us/library/windows/desktop/ms682453%28v=vs.85%29.aspx

fonte
7

O motivo pelo qual o C ++ pode compilar o C é apenas para "compatibilidade com versões anteriores" (evite reescrever o código de trabalho existente).

Mas C ++ tem uma filosofia diferente em relação a c. Misturá-los não faz um bom serviço para os dois.

A maneira como C e C ++ gerenciam a E / S pode confiar em uma maneira diferente de gerenciar o estado interno da E / S. Portanto, pelo menos, use entrada e saída de forma consistente.

E nos programas C ++ respeitam o estilo C ++ (a menos que seja especificamente necessário fazer isso em outro lugar)

Emilio Garavaglia
fonte
5

Eu diria que aprender C primeiro é, IMHO, uma boa idéia. Dessa forma, as pessoas começam a entender o hardware para o qual escrevem o software.

Misturar esses dois idiomas não é uma boa ideia, no entanto. Como você obtém a complexidade insana do C ++, juntamente com a manipulação de bits brutos comum a C.

Como você pode ver, mesmo em um exemplo tão simples como o seu, há problemas de sincronização com diferentes tipos de fluxos e buffer interno. Mas também, a abordagem C & C ++ não é mais flexível por nenhum meio. Alterne para a classe xe não há operadores para usar streaming e outras coisas.

É complicado...

Eu realmente acho que um bom programador de C ++ deve saber como os bits são movidos por trás de cada construção e quais são os comportamentos ocultos.

Mas aprender C ++, pelo menos mais de 50%, requer mais de 5 anos de codificação profissional, e você simplesmente não pode gerenciar isso no currículo de seis meses com 20 ou mais horas de experiência prática.

Se eu usasse construções C ++ em C, não usaria fluxos, eles são muito simples do ponto de vista dos pássaros e fazem as pessoas acreditarem que o desenvolvimento de software é fácil, mas ocultam complexidades extras sem muitos benefícios em muitas situações.

Classes de wrapper RAII, modelos, sobrecargas, correção de const e classes abstratas puras para interfaces comuns (não use a maneira Java f-ng aqui, POR FAVOR!) São boas candidatas. Porque eles agregam segurança, generalidade e facilidade de uso, que são muito importantes para projetos da vida real. Lembre-se de lembrar de coisas como destruição virtual, a natureza explosiva da construção de cópias padrão, sobrecarga de tempo de execução, correção de const etc., também aqui.

Codificador
fonte