3 votes

Quelle est la méthode recommandée pour créer une bibliothèque avec plusieurs classes ?

Je suis relativement novice en matière de C++ (j'ai une expérience antérieure en Python et j'ai tâté de Java) et j'écris un petit programme pour me familiariser avec ce langage. Dans le cadre de ce programme, j'écris une classe pour décoder certaines données et j'en écrirai éventuellement une autre pour effectuer l'encodage. Le code est quelque chose que je suis sûr de réutiliser assez souvent et j'ai pensé qu'il serait intéressant de créer une bibliothèque dans le cadre du projet. Ma question est la suivante : quelle est la meilleure pratique pour créer une bibliothèque ?

Edit : (Révisé)

Après avoir posé cette question, j'ai réalisé que je ne savais pas ce que je ne savais pas. J'ai fait d'autres recherches et cela devrait m'aider à préciser ma question :

  • Je développe en Qt Creator. Donc les spécificités liées à Qt seraient utiles, mais pas nécessaires.
  • J'ai créé un nouveau projet de bibliothèque statique dans Qt (MyCodec) qui, actuellement, a une classe définie appelée MyDecoder.
  • En tant que bibliothèque, je suppose que, pour ajouter MyEncoder, il suffit de créer un autre fichier de classe/en-tête.
  • Je ne suis pas sûr de ce qui va se passer ensuite. Est-ce que je construis simplement la bibliothèque ? Je crois comprendre que cela créera (sous Windows) un fichier .lib et un fichier .h. Y a-t-il quelque chose que je devrais faire avant cette étape ? Existe-t-il des options qui affectent la manière dont j'interagis avec la bibliothèque ?
  • Dois-je simplement inclure ce fichier d'en-tête dans mon programme pour accéder aux deux classes que j'ai écrites ?
  • J'ai trouvé de nombreuses réponses sur l'ajout d'un fichier .lib à un projet dans Qt, je n'ai donc pas besoin de ces informations.

Question originale : (pour le contexte)

Ma première idée est qu'il serait plus pratique de créer MyLib qui inclut les classes MyEncoder et MyDecoder.

  • Si je devais le faire de cette manière, dois-je simplement déclarer les deux classes dans l'en-tête ?

  • J'aimerais créer une DLL à partir de cette bibliothèque pour des raisons de portabilité et d'expérience. Je suis sûr qu'il existe de nombreuses informations sur la création et l'utilisation des DLL (ce qui n'est pas le sujet de cette question), mais s'il existe un tutoriel particulièrement bon (pour Qt), merci de le transmettre.

  • Je suppose qu'il serait préférable d'utiliser des espaces de noms distincts pour MyEncoder et MyDecoder pour cette mise en œuvre, plutôt qu'un seul espace de noms pour MyLib ?

Je vois un inconvénient à cette méthode, à savoir la taille de l'application, puisque l'inclusion de MyLib.h comprendrait le code du codeur et du décodeur (si le codeur et le décodeur étaient des applications distinctes). Ceci en supposant que je n'utilise pas de DLL.

Je suppose que ce que je veux dire est :

  • Quelles sont les méthodes disponibles (et recommandées) ?
  • Quels sont les inconvénients de chacun ?
  • Où puis-je trouver de la documentation (didacticiels/exemples) sur ce sujet spécifique ? Mes efforts de recherche n'ont pas donné beaucoup de résultats.

Si cela peut aider à être plus précis, je fais mon développement en utilisant Qt 4.7.4 dans Qt Creator.

6voto

Gerald Points 13865

Une "meilleure pratique" en C++ en ce qui concerne les bibliothèques est généralement "vous payez pour ce que vous utilisez".

La façon dont cela s'applique à votre question est que vous auriez MyEncoder et MyDecoder dans des fichiers d'en-tête séparés. Ainsi, si l'utilisateur veut utiliser un MyEncoder, il doit inclure MyEncoder.h, s'il veut utiliser MyDecoder, il doit inclure MyDecoder.h, et s'il veut utiliser les deux, il doit inclure les deux en-têtes.

L'éditeur de liens n'inclura généralement que les parties du code que vous utilisez dans l'exécutable. Il n'y a donc pas de pénalité en termes de taille de code, mais il y a une pénalité en termes de temps de compilation, en particulier si vous commencez à utiliser des techniques de template avancées dans vos classes. Les temps de compilation peuvent être assez longs dans les grands projets, il est donc important de pouvoir inclure uniquement ce que vous allez utiliser.

Bien sûr, il est parfois pratique de tout inclure dans un seul en-tête. Voici donc ce que vous pourriez avoir :

  • MyEncoder.h
  • MyDecoder.h
  • MyCodec.h

et alors MyCodec.h pourrait inclure à la fois MyEncoder.h et MyDecoder.h

Il n'y a probablement aucune bonne raison d'avoir MyEncoder et MyDecoder dans des espaces de noms différents, en supposant qu'ils sont censés fonctionner sur le même type de données.

Vous pourriez avoir quelque chose comme un espace de nom MyCodec, et déclarer MyEncoder et MyDecoder dans cet espace de nom.

Mis à jour pour votre révision :

En tant que bibliothèque, je suppose que, pour ajouter MyEncoder, je crée juste un autre fichier de classe/en-tête.

C'est une hypothèse correcte.

Je suis incertain de ce qui se passera ensuite. Est-ce que je construis juste la bibliothèque ? D'après ce que j'ai compris, cela va créer (sous Windows) un fichier .lib et un fichier .h. Y a-t-il quelque chose que je devrais faire avant cette étape ? Est-ce que y a-t-il des options qui affecteront la façon dont j'interagirai avec le programme ?

Je n'ai pas utilisé Qt creator depuis un certain temps, donc je ne peux pas parler avec autorité sur ce sujet ou sur la façon d'accéder aux options pertinentes. Mais en règle générale, vous voudrez avoir au moins 2 versions de votre bibliothèque ; une version debug et une version release. Si votre bibliothèque utilise les bibliothèques Qt, alors lorsqu'une application se lie à la version de débogage de votre bibliothèque, elle devra avoir la version de débogage des bibliothèques partagées Qt dans son chemin, et si elle se lie à votre version release, elle devra avoir la version release des librairies Qt.

Il peut également y avoir des options pour savoir si vous souhaitez établir un lien statique avec les bibliothèques d'exécution standard C++ ou un lien dynamique avec les DLL.

Mais essentiellement oui, il suffit de construire la bibliothèque et ensuite l'application qui l'utilise liera la bibliothèque à l'exécutable.

Dois-je simplement inclure ce fichier d'en-tête dans mon programme pour accéder aux deux classes que j'ai écrites ?

Vous incluez le fichier d'en-tête et créez un lien vers le fichier .lib. C'est tout ce que vous devez faire.

5voto

Kuba Ober Points 18926

Ceci s'applique à Qt Creator 2.4.1.

Tout d'abord, pour utiliser et déboguer votre bibliothèque, vous devez avoir un projet supérieur hiérarchique avec deux sous-projets : un pour la bibliothèque, et un pour une application qui l'utilise. De cette façon, Creator reconstruira tout ce qui a été modifié avant d'exécuter l'application. Ainsi, si vous modifiez les fichiers sources de la bibliothèque, celle-ci sera reconstruite automatiquement. ainsi que l'application sera reliée.

Je montrerai, étape par étape, comment créer les trois projets nécessaires (la bibliothèque, l'application et le projet principal), pour aboutir à une application et une bibliothèque minimales, constructibles et déboguables. Vous pouvez ajouter facilement d'autres sous-bibliothèques en suivant les mêmes étapes.

Création des projets

  1. Créez un dossier pour vos projets.

  2. Top Projet

    • File->New File or Project, Other Project, Subdirs Project, Choose
    • Nommez le projet top et le placer dans le dossier que vous avez créé à l'étape 1.
    • Cliquez sur "Done & Add Subproject".
  3. Projet de bibliothèque - une nouvelle fenêtre de projet apparaît suite au clic de l'étape précédente.

    • Other Project, C++ Library, Choose
    • Type : changer en Statically Linked Library.
    • Nommez le projet library et le mettre dans le top qui a été créé dans le dossier précédent précédente. Ce dossier devrait être déjà sélectionné par défaut pour vous.
    • Cliquez dessus, sélectionnez le module QtCore à utiliser par le projet de bibliothèque, laissez tout le reste aux valeurs par défaut.
  4. Projet d'application - cliquez à droite sur le top dans le volet Projets (pas dans top.pro)

    • Qt Widget Project, Qt Gui Application, Choose
    • Nommez le projet app et le mettre dans le top qui a été créé à l'étape 2. Ce dossier devrait être déjà sélectionné par défaut pour vous.
    • Cliquez dessus, laissez tout aux paramètres par défaut.

Vous devriez maintenant avoir un top projet qui a app y library en tant que sous-projets. Appuyez sur C-B (Ctrl-B ou Command-B, selon votre plate-forme) pour le construire. La construction devrait se dérouler sans erreur.

Définition des dépendances

Liens avec la bibliothèque

En app subproject n'utilise pas encore notre bibliothèque. Pour avoir le app lien avec notre bibliothèque :

  1. Cliquez à droite sur app dans le volet Projets ( no sur app.pro), choisissez Add Library...

  2. Choisissez Internal Library , Continuer

  3. En library est le seul choix possible et est déjà sélectionné. Cliquez jusqu'à la fin.

En app est désormais lié de manière statique au projet library . Changez n'importe quel fichier dans le app (un changement d'espace fera l'affaire) pour forcer une construction, puis appuyez sur C-B pour une construction. La construction devrait se dérouler correctement.

Ajout d'une dépendance de niveau supérieur sur la bibliothèque

En app sera reconstruit si la bibliothèque est modifiée, mais il n'y a rien pour garantir que le système make construira d'abord le sous-projet de la bibliothèque, avant de commencer à construire l'application. De telles informations appartiennent au toplevel top.pro dossier de projet.

Ouvrir top.pro et ajoutez une ligne CONFIG += ordered . Le fichier devrait ressembler à ceci :

TEMPLATE = subdirs

SUBDIRS += \
    library \
    app

CONFIG += ordered

Assurez-vous que les SUBDIRS sont correctement ordonnés : la bibliothèque vient en premier avant l'application. Si l'ordre est incorrect, vous pouvez mélanger les entrées dans l'ordre correct. La barre oblique inversée \ est un caractère de continuation de ligne. Il ne doit pas y avoir d'espace après \ ¡!

Sauvegarder le fichier (C-S), cliquer avec le bouton droit de la souris sur l'icône de l'ordinateur. top et sélectionnez Rebuild Project "top". La construction devrait se terminer sans erreur. Les avertissements sont acceptés.

Sélection de la construction

Dans le panneau inférieur gauche de Qt Creator, il y a un panneau avec un bouton de construction (un marteau), un bouton d'exécution (un triangle), un bouton de débogage (un triangle avec un bug), un sélecteur de construction (un portable avec top le nom du projet au-dessus, et la configuration de construction élidée en dessous. Cliquez sur le sélecteur de build, et assurez-vous que vous sélectionnez le Build qui se termine par Debug . Cette construction est configurée pour produire les symboles de débogage nécessaires pour l'exécuter sous le débogueur. Nous en aurons besoin plus tard.

Mise en œuvre de la bibliothèque

Nous allons maintenant ajouter du code à la classe Library qui a été créée pour nous par Qt Creator. Ouvrez la classe library.h y library.cpp fichiers. Le code ajouté est simplement une méthode statique dans la classe Library. Cette méthode sera utilisée dans l'application pour montrer que les deux pièces se sont en fait liées. Le contenu des deux fichiers est ci-dessous.

//library.h
#ifndef LIBRARY_H
#define LIBRARY_H

#include <QString>

class Library {
public:
    Library();
    static QString string();
};

#endif // LIBRARY_H

//library.cpp
#include "library.h"

Library::Library()
{}

QString Library::string()
{
    return "I come from the library";
}

Appuyez sur C-B, le code devrait se reconstruire sans erreur.

Mise en œuvre de l'application

Utilisons maintenant l'API de la bibliothèque de notre app . Ouvrez le mainwindow.cpp y mainwindow.h et modifier comme ci-dessous.

//mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QScopedPointer>
#include <QMainWindow>

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();

private:
    QScopedPointer<Ui::MainWindow> const ui;
};

#endif // MAINWINDOW_H

//mainwindow.cpp
#include <QVBoxLayout>
#include <QLabel>
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "library.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    QVBoxLayout * layout = new QVBoxLayout();
    QLabel * label = new QLabel(Library::string(), centralWidget());
    layout->addWidget(label);
    centralWidget()->setLayout(layout);
}

MainWindow::~MainWindow()
{}

Appuyez sur C-B, le projet devrait se construire correctement.

Nous pouvons alors définir un point d'arrêt dans le Library::string() pour vérifier que non seulement le code est appelé, mais que le débogueur fonctionne dans tous les sous-projets. Dans library.cpp cliquez dans la zone grise à gauche du numéro de ligne dans la fenêtre return "I come from the library"; ligne. Un cercle rouge avec un petit sablier apparaîtra à l'endroit où vous avez cliqué : cela signifie qu'un point d'arrêt en attente a été défini.

Appuyez ensuite sur C-Y pour lancer le projet dans le débogueur. Le seul sous-projet exécutable est l'application, et il sera automatiquement choisi comme projet de démarrage.

Le cercle du point d'arrêt finira par perdre son sablier à mesure que le débogueur lira les fichiers de symboles et trouvera l'emplacement de notre point d'arrêt. Peu après, le code s'arrêtera dans la méthode Library::string() -- elle est appelée par le constructeur de MainWindow. Appuyez sur C-Y pour continuer l'exécution de app .

La fenêtre principale apparaît alors, avec I come from the library texte visible à l'intérieur de celui-ci. Ce texte a été placé sur une étiquette qui a été ajoutée dans le constructeur de MainWindow.

2voto

Martin Beckett Points 60406

Il n'y a pas de lien entre une bibliothèque et les cours. Le concept de bibliothèque est apparu bien avant l'OO et il n'y a rien dans le format de bibliothèque en c/c++ qui ait quelque chose à voir avec les classes ou les espaces de noms.

Si vous utilisez des bibliothèques statiques (pas de DLL), l'éditeur de liens n'extraira que les fonctions dont le programme a besoin et la taille de la bibliothèque n'a donc aucune importance. Avec les librairies dynamiques (dlls), vous devez expédier toute la dll et il y a donc une raison de n'inclure que les librairies similaires dans une dll - c'est pourquoi Qt a par exemple QtOpenGl.dll séparé de QtGui.dll - si vous n'utilisez pas opengl, il n'y a pas besoin d'inclure la librairie. La taille du fichier d'en-tête n'a pas d'importance pour le programme fini - bien que de très gros fichiers d'en-tête conduisent à des compilations plus lentes (à moins que vous ayez des en-têtes précompilés).

Un espace de nom est utilisé pour montrer que ces classes fonctionnent ensemble et pour éviter les conflits avec d'autres classes. J'utiliserais donc un seul espace de nom pour vos classes de codage/décodage.

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