85 votes

Le déplacement du C++ à C

Après quelques années de codage en C++, on m'a récemment offert un travail de codage en C, dans le sous-champ.

En mettant de côté la question de savoir si c'est bon ou mauvais pour rejeter C++ dans le sous-domaine, il y a certaines fonctionnalités/les expressions idiomatiques en C++ je me manques beaucoup. Juste pour en nommer quelques-uns:

  • Générique, type-safe structures de données (à l'aide de modèles).
  • RAII. En particulier dans les fonctions avec plusieurs points de retour, par exemple, ne pas avoir à se souvenir de la libération du mutex sur chaque point de retour.
  • Les destructeurs en général. I. e. vous écrivez un d'tor une fois pour MyClass, alors si une instance de Maclasse est un membre de MyOtherClass, MyOtherClass n'a pas explicitement deinitialize l'instance de Maclasse - son d'tor est appelé automatiquement.
  • Les espaces de noms.

Quelles sont vos expériences en mouvement à partir de C++ à C?
De ce que C substituts avez-vous trouver votre favori des fonctionnalités C++/idiomes? Avez-vous découvrir de toute C des fonctionnalités que vous souhaitez C++?

71voto

Mike DeSimone Points 20059

Travail sur un projet intégré, j'ai essayé de travailler dans tous les C une fois, et ne pouvaient tout simplement pas le supporter. Il était tellement détaillé qu'il a du mal à lire quoi que ce soit. Aussi, j'ai aimé la optimisé-pour-embedded conteneurs j'avais écrit, qui avait à son tour en beaucoup moins fort et plus difficile à corriger #define blocs.

Code en C++ ressemblait à:

if(uart[0]->Send(pktQueue.Top(), sizeof(Packet)))
    pktQueue.Dequeue(1);

se transforme en:

if(UART_uchar_SendBlock(uart[0], Queue_Packet_Top(pktQueue), sizeof(Packet)))
    Queue_Packet_Dequeue(pktQueue, 1);

qui beaucoup de gens vont probablement dire que c'est bien, mais devient ridicule si vous devez faire plus d'un couple de "méthode" à des appels à la ligne. Deux lignes de C++ serait à son tour tenu cinq de C (en raison de 80-char limites de longueur de ligne). Les deux devraient générer le même code, c'est pas comme si le processeur cible soigné!

Une seule fois (en 1995), j'ai essayé d'écrire beaucoup de C pour un multiprocesseur de traitement de données de programme. Le genre où chaque processeur possède sa propre mémoire et le programme. Les fournisseur compilateur est un compilateur C (une sorte de HighC dérivés), de leurs bibliothèques ont été à code source fermé, donc je ne pouvais pas utiliser GCC pour construire, et à leurs Api ont été conçus avec l'état d'esprit que vos programmes s'agit principalement de la initialiser/processus/mettre fin à la variété, de sorte inter-processeur de communication a été, au mieux, rudimentaire.

J'ai eu environ un mois avant que j'ai donné, a trouvé une copie du cfront, et piraté dans le makefile si je pouvais utiliser C++. Cfront n'a même pas le soutien de modèles, mais le code C++ est beaucoup, beaucoup plus claire.

Générique, type-safe structures de données (à l'aide de modèles).

La chose la plus proche C est à des modèles est de déclarer un fichier d'en-tête avec beaucoup de code qui ressemble à ceci:

TYPE * Queue_##TYPE##_Top(Queue_##TYPE##* const this)
{ /* ... */ }

ensuite, tirez-le avec quelque chose comme:

#define TYPE Packet
#include "Queue.h"
#undef TYPE

Notez que cela ne fonctionne pas pour les types composés (par exemple, pas de files d'attente d' unsigned char) à moins de faire un typedef première.

Oh, et n'oubliez pas, si ce code n'est pas utilisé n'importe où, alors vous ne savez même pas si elle est syntaxiquement correcte.

EDIT: encore Une chose: vous devez manuellement gérer l'instanciation de code. Si votre "template" le code n'est pas toutes les fonctions en ligne, alors vous aurez à mettre dans un certain contrôle pour s'assurer que les choses se instancié qu'une seule fois donc votre éditeur de liens n'est pas de cracher un tas de "plusieurs instances de Foo" erreurs.

Pour ce faire, vous aurez à mettre la non-incorporé des trucs dans la "mise en œuvre" de section dans le fichier d'en-tête:

#ifdef implementation_##TYPE

/* Non-inlines, "static members", global definitions, etc. go here. */

#endif

Et puis, dans un lieu dans tout votre code par modèle variante, vous devez:

#define TYPE Packet
#define implementation_Packet
#include "Queue.h"
#undef TYPE

Aussi, cette mise en œuvre de l'article doit être en dehors de la norme #ifndef/#define/#endif litanie, parce que vous pouvez inclure le modèle d'en-tête de fichier dans un autre fichier d'en-tête, mais faut instancier par la suite, dans un .c le fichier.

Yep, ça devient laid rapide. C'est pourquoi la plupart des programmeurs C, n'essayez même pas.

RAII.

En particulier dans les fonctions avec plusieurs points de retour, par exemple, ne pas avoir à se souvenir de la libération du mutex sur chaque point de retour.

Eh bien, oubliez votre joli code et de s'habituer à l'ensemble de vos points de retour (à l'exception de la fin de la fonction) en cours de gotos:

TYPE * Queue_##TYPE##_Top(Queue_##TYPE##* const this)
{
    TYPE * result;
    Mutex_Lock(this->lock);
    if(this->head == this->tail)
    {
        result = 0;
        goto Queue_##TYPE##_Top_exit:;
    }

    /* Figure out `result` for real, then fall through to... */

Queue_##TYPE##_Top_exit:
    Mutex_Lock(this->lock);
    return result;
}

Les destructeurs en général.

I. e. vous écrivez un d'tor une fois pour MyClass, alors si une instance de Maclasse est un membre de MyOtherClass, MyOtherClass n'a pas explicitement deinitialize l'instance de Maclasse - son d'tor est appelé automatiquement.

Construction de l'objet doit être explicitement traitées de la même manière.

Les espaces de noms.

C'est en fait un simple correctif: simplement ajouter un préfixe sur chaque symbole. C'est la cause première de la source de ballonnements que j'ai parlé plus tôt (étant donné que les classes sont implicites des espaces de noms). La C les gens ont vécu cela, eh bien, jamais, et ne sera probablement pas voir ce qu'est l'affaire.

YMMV

18voto

Jens Gustedt Points 40410

J'ai déménagé à partir de C++ à C pour une raison différente (une sorte de réaction allergique ;) et il y a seulement quelques chose qui me manque et certaines choses que j'ai gagné. Si vous vous en tenez à C99, si vous pouvez, il y a des constructions qui vous permettent de programmer tout à fait bien et en toute sécurité, en particulier

  • désigné initialiseurs (éventuellement combiné avec des macros) faire l'initialisation de simples classes indolore que les constructeurs
  • composé littéraux pour les variables temporaires
  • for-portée variable peut vous aider à faire de périmètre lié à la gestion des ressources, en particulier de veiller à l' unlock des mutex ou free de tableaux, même sous préliminaire fonction renvoie
  • __VA_ARGS__ macros peuvent être utilisés pour avoir des arguments par défaut pour les fonctions et pour faire le code de dérouler
  • inline fonctions et macros qui se combinent bien à remplacer (sorte de) fonctions surchargées

9voto

d.s. Points 71

La différence entre le C et le C++ est la prévisibilité du comportement du code.

Il est plus facile de prédire avec une grande précision ce que votre code en C, en C++, il pourrait devenir un peu plus difficile à venir avec une prédiction exacte.

La prévisibilité dans C vous donne un meilleur contrôle de ce que votre code est en train de faire, mais cela signifie également que vous avez à faire plus de choses.

En C++, vous pouvez écrire moins de code pour obtenir la même chose en fait, mais (à lea pour moi) j'ai parfois de la difficulté à savoir comment le code objet est mis en mémoire et c'est le comportement attendu.

8voto

MOnsDaR Points 3027

Rien de tel que la STL existe pour C.
Il y a des libs disponibles qui fournissent des fonctionnalités similaires, mais il n'est pas builtin plus.

Pense que ce serait un de mes plus gros problèmes... Sachant avec quel outil j'ai pu résoudre le problème, mais n'ayant pas les outils disponibles dans la langue, que j'ai à utiliser.

7voto

Dan Points 6319

Dans ma ligne de travail - qui est intégré, en passant, je suis constamment des allers-et-retours entre le C et le C++.

Quand je suis en C, je m'ennuie à partir de C++:

  • les modèles (y compris mais non limité à des conteneurs STL). - Je les utiliser pour des choses comme des guichets, des tampons, des piscines, etc. (construit ma propre bibliothèque de modèles de classe et les modèles de fonction que j'utilise dans différents projets intégrés)

  • très puissant de la bibliothèque standard

  • les destructeurs, qui, bien sûr, faire RAII possible (mutex, interrompre, de désactiver, de traçage, etc.)

  • spécificateurs d'accès, de mieux faire respecter les qui peut utiliser (ne pas voir) ce que

J'utilise l'héritage sur les grands projets, et C++de prise en charge intégrée de elle est beaucoup plus propre et plus agréable que la C "hack" de l'incorporation de la classe de base comme le premier membre (pour ne pas mentionner automatique invocation de constructeurs, init. les listes, etc.) mais les éléments énumérés ci-dessus sont ceux qui me manque le plus.

Aussi, probablement seulement environ un tiers de l'embedded C++ projets, je travaille sur l'utilisation des exceptions, donc j'ai pris l'habitude de vivre sans eux, donc je ne les manquez pas trop quand je suis rentrée C.

Sur le revers de la médaille, quand je reviens dans un projet C avec un nombre important de développeurs, il existe des classes de C++ problèmes que j'ai l'habitude d'expliquer aux gens qui disparaissent. La plupart des problèmes en raison de la complexité de C++, et les gens qui pensent qu'ils savent ce qu'il se passe, mais ils sont vraiment à la "C with classes" du C++ courbe confiance.

Étant donné le choix, je préfère le à l'aide de C++ sur un projet, mais seulement si l'équipe est assez solide sur la langue. Aussi, bien sûr, en supposant que ce n'est pas un 8K µC projet où je suis effectivement écrit "C" de toute façon.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X