MVC (headers + class): erreur dans mon code c++

Résolu
JLesage Messages postés 33 Date d'inscription mercredi 14 novembre 2012 Statut Membre Dernière intervention 23 février 2024 - 3 nov. 2023 à 14:14
JLesage Messages postés 33 Date d'inscription mercredi 14 novembre 2012 Statut Membre Dernière intervention 23 février 2024 - 8 nov. 2023 à 17:23

Bonjour. Je suis débutant en c++ et j'ai essayé de mettre en place le MVC dans un petit programme, mais j'ai des erreurs que je n'arrive pas à corriger. J'utilise Code::Blocks pour le code et j'ai créé plusieurs classes et des fichiers d'entêtes séparés. Ici, j'ai mis tout le code ensemble pour faire simple, comme vous pouvez le voir. J'ai vraiment besoin de votre aide pour faire fonctionner le programme. Merci.

//Headers
//Header class 1


#ifndef MODEL_PERSONNE_H
#define MODEL_PERSONNE_H

#include <string>

class Model_Personne
{
    public:
        Model_Personne(std::string prenom, std::string nom, std::string profession, int age);
        virtual ~Model_Personne();

        //Setters
        void setPrenom(std::string unPrenom);

        void setNom(std::string unNom);

        void setProfession(std::string uneProfession);

        void setAge(int unAge);


        //Getters

        std::string getPrenom();

        std::string getNom();

        std::string getProfession();

        int getAge();

    protected:

    private:
        std::string prenom;
        std::string nom;
        std::string profession;
        int age;
};

#endif // MODEL_PERSONNE_H



//Header class 2

#ifndef VIEW_PERSONNE_H
#define VIEW_PERSONNE_H

#include <string>

class View_Personne
{
    public:
        View_Personne();
        virtual ~View_Personne();
        void afficherPersonne(std::string prenom, std::string nom, std::string profession, int age);

    protected:

    private:
};

#endif // VIEW_PERSONNE_H


//Header class 3

#include "Controller_Personne.h"
#include "Model_Personne.h"
#include "View_Personne.h"

#include <string>

Controller_Personne::Controller_Personne(Model_Personne unePersonne, View_Personne uneVuePersonne)
{
    personne = unePersonne;
    vue = uneVuePersonne;
}
Controller_Personne::~Controller_Personne()
{
    //dtor
}

//Setters
void Controller_Personne::setPrenom(std::string unPrenom){
    personne.setPrenom(unPrenom);
}

void Controller_Personne::setNom(std::string unNom){
    personne.setNom(unNom);
}

void Controller_Personne::setProfession(std::string uneProfession){
    personne.setProfession(uneProfession);
}

void Controller_Personne::setAge(int unAge){
    personne.setAge(unAge);
}


//Getters

std::string Controller_Personne::getPrenom(){
    return personne.getPrenom();
}

std::string Controller_Personne::getNom(){
    return personne.getNom();
}

std::string Controller_Personne::getProfession(){
    return personne.getProfession();
}

int Controller_Personne::getAge(){
    return personne.getAge();
}

void Controller_Personne::getAffichage(){
    vue.afficherPersonne(personne.getPrenom(), personne.getNom(), personne.getProfession(), personne.getAge());
}



//Class - fichiers ".cpp"

//Class 1

#include "Model_Personne.h"

#include <string>


Model_Personne::Model_Personne(std::string unPrenom, std::string unNom, std::string uneProfession, int unAge )
{
    //ctor
    prenom=unPrenom;
    nom=unNom;
    profession=uneProfession;
    age=unAge;
}

Model_Personne::~Model_Personne()
{
    //dtor
}

//Setters
void Model_Personne::setPrenom(std::string unPrenom){
    this->prenom=unPrenom;
}

void Model_Personne::setNom(std::string unNom){
    this->nom=unNom;
}

void Model_Personne::setProfession(std::string uneProfession){
    this->profession=uneProfession;
}

void Model_Personne::setAge(int unAge){
    this->age=unAge;
}


//Getters

std::string Model_Personne::getPrenom(){
    return this->prenom;
}

std::string Model_Personne::getNom(){
    return this->nom;
}

std::string Model_Personne::getProfession(){
    return this->profession;
}

int Model_Personne::getAge(){
    return this->age;
}


//Class 2

#include "View_Personne.h"

#include <string>

View_Personne::View_Personne()
{

}

View_Personne::~View_Personne()
{
    //dtor
}


void View_Personne::afficherPersonne(std::string unPrenom, std::string unNom, std::string uneProfession, std::string unAge){
    std::cout<<"Prénom: "<<unPrenom<<std::endl;
    std::cout<<"Nom: "<<unNom<<std::endl;
    std::cout<<"Profession: "<<uneProfession<<std::endl;
    std::cout<<"Âge: "<<unAge<<std::endl;
}



//Class 3

#include "Controller_Personne.h"
#include "Model_Personne.h"
#include "View_Personne.h"

#include <string>

Controller_Personne::Controller_Personne(Model_Personne unePersonne, View_Personne uneVuePersonne)
{
    personne = unePersonne;
    vue = uneVuePersonne;
}
Controller_Personne::~Controller_Personne()
{
    //dtor
}

//Setters
void Controller_Personne::setPrenom(std::string unPrenom){
    personne.setPrenom(unPrenom);
}

void Controller_Personne::setNom(std::string unNom){
    personne.setNom(unNom);
}

void Controller_Personne::setProfession(std::string uneProfession){
    personne.setProfession(uneProfession);
}

void Controller_Personne::setAge(int unAge){
    personne.setAge(unAge);
}


//Getters

std::string Controller_Personne::getPrenom(){
    return personne.getPrenom();
}

std::string Controller_Personne::getNom(){
    return personne.getNom();
}

std::string Controller_Personne::getProfession(){
    return personne.getProfession();
}

int Controller_Personne::getAge(){
    return personne.getAge();
}

void Controller_Personne::getAffichage(){
    vue.afficherPersonne(personne.getPrenom(), personne.getNom(), personne.getProfession(), personne.getAge());
}


//Main

#include "Model_Personne.h"
#include "View_Personne.h"
#include "Controller_Personne.h"

#include <string>

int main(){
    Model_Personne unePersonne("Jacques", "Baeur", "Artiste-Informaticien", 36);
    View_Personne uneVuePersonne();
    Controller_Personne unControlleurPersonne(unePersonne, uneVuePersonne);
    unControlleurPersonne.getAffichage();
}



Linux / Firefox 119.0

4 réponses

JLesage Messages postés 33 Date d'inscription mercredi 14 novembre 2012 Statut Membre Dernière intervention 23 février 2024 5
4 nov. 2023 à 01:29

@[Dal] StatutContributeur, tu as raison. Merci pour la remarque. Voici le contenu de Controller_Personne.h:

#ifndef CONTROLLER_PERSONNE_H
#define CONTROLLER_PERSONNE_H

#include "Model_Personne.h"
#include "View_Personne.h"

#include <string>

class Controller_Personne
{
    public:
        Controller_Personne(Model_Personne unePersonne, View_Personne uneVuePersonne);
        virtual ~Controller_Personne();

        Model_Personne personne;
        View_Personne vue;

        //Setters
        void setPrenom(std::string unPrenom);

        void setNom(std::string unNom);

        void setProfession(std::string uneProfession);

        void setAge(int unAge);


        //Getters

        std::string getPrenom();

        std::string getNom();

        std::string getProfession();

        int getAge();

        void getAffichage();


    protected:

    private:

};

#endif // CONTROLLER_PERSONNE_H
2
mamiemando Messages postés 33079 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 23 avril 2024 7 749
Modifié le 6 nov. 2023 à 22:10

Bonjour,

Avant, tout essaye dans tes prochains message de poster un exemple minimal qui permet de reproduire ton problème. Ici tu dis avoir trois problèmes, ce devrait donc, une fois minimisés, donner trois fils de discussion.

Il y a plusieurs choses qui ne vont pas. 

  • Si tu appelles le constructeurs par défaut, pas besoin d'ajouter () :
ViewPersonne uneVuePersonne;
  • Tes constructeurs ne sont pas correctement écrits. Cela devrait plutôt ressembler à :
Model_Personne::Model_Personne(
    std::string prenom,
    std::string nom,
    std::string profession,
    int age
):
    prenom(prenom),
    nom(nom),
    profession(profession),
    age(age)
{}
  • Note que dans une telle situation, le corps du constructeur est vide, on peut donc le déporter intégralement dans le header.
  • Le type de l'âge n'est pas cohérent partout (parfois int, parfois std::string), du coup le linker ne parvient pas à retrouver ses billes.
  • La signature de ControllerPersonne n'est pas cohérente à la déclaration et à l'appel 
  • Là où tu utilises std::cout, tu devrais inclure <iostream>
  • La fonction main devrait retourner un entier (le code d'exécution, 0 si tout va bien, un code d'erreur documenté sinon)

Par ailleurs, un certain nombre d'améliorations pourraient être apportées :

  • Plutôt que passer les paramètres par recopie, tu devrais les passer autant que possible par référence (voir const référence), cela serait plus efficace.
  • Tes signatures de fonctions devraient indiquer quels paramètres restent constant (avec le mot clé const). Si this est maintenu constant, il faut aussi ajouter const derrière la parenthèse fermante du prototype.
class Controller_Personne {
private:
    std::string prenom
public:
    std::string getPrenom() const;
}

std::string Controller_Personne getPrenom() const {
    return prenom;
}
  • Tu peux sous-entendre this-> quand il n'y a pas d’ambiguïté, cela allège le code. Mais dans un setter par exemple il peut être nécessaire, par exemple pour écrire :
void ModelPersonne::setNom(std::string nom) {
    this->nom = nom;
} 

Exemple :

  • Il ne sert à rien d'ouvrir plusieurs fois std::cout, autant le faire en une instruction.
  • Pour alléger le code, si tu es dans un ".cpp", tu peux parfaitement utiliser using namespace std; ou mieux, using std::cout; using std::endl; (voir ici). Par contre il ne faut jamais le faire dans un ".hpp"
  • Généralement, on adopte soit le style camel case,  soit tout en minuscules avec des _ (comme dans le kernel linux), mais les deux à la fois c'est bizarre. Tant qu'on est dans le nommage, ce serait pas mal d'adopter un style tout en français, ou mieux, tout en anglais.
class VoitureDeSport {
    VoitureDeSport(){}
};

int main() {
    VoitureDeSport voitureDeSport();
    return 0;
}
class voiture_de_sport_t {
    voiture_de_sport_t(){}
};

int main() {
    voiture_de_sport_t voiture_de_sport();
    return 0;
}
  • On peut légèrement optimiser le code en ajoutant le mot clé inline devant les fonctions courtes dans le ".hpp" (mais pas dans le .cpp). Concrètement, le compilateur substitue l'appel par le corps de la fonction. Cela concerne typiquement les getters et les setters.
  • Dans le cas des fonctions inline, on peut considérablement alléger l'implémentation des fonctions inline en déportant le corps de leurs fonctions dans le ".hpp". Cependant, seul le corps des fonctions inline peut ainsi être déporté.
  • Si une classe ne comporte que des attributs et méthodes publiques, autant utiliser directement une structure (qui en C++, peut parfaitement avoir des méthodes).
  • Déclarer un destructeur (virtuel) n'est pas nécessaire si la classe n'est pas virtuelle. Tu peux les sous-entendre si tu ne fais rien dedans (ce qui est ton cas). Par contre, une classe virtuelle impose la déclaration d'un destructeur virtuel.
  • La classe ViewPersonne a un intérêt assez limité, vu qu'elle ne stocke rien.
  • Pour plus de lisibilité, je trouve mieux de déclarer les attributs (souvent privés) avant les méthodes. Cela permet de se faire une idée de la taille d'une instance en mémoire. Mais là c'est plus une affaire de goût.
  • La méthode getAffichage est mal nommée, elle suggère qu'on récupère un objet affichage. Il serait mieux de le renommer afficherPersonne pour être cohérent avec le reste du code.
  • Essaye de faire tenir tes lignes en moins de 80 caractères, quitte à passer à la ligne. Pense à mettre des espaces autour des espaces. Autant de facteurs qui améliorent la lisibilité.

Une fois toutes ces remarques appliquées (je n'ai juste pas fait les using std::cout; et using std::endl;) qui ne plaisent pas à tout le monde on obtient :

// ViewPersonne.hpp

#ifndef VIEW_PERSONNE_H
#define VIEW_PERSONNE_H

#include <string>

struct ViewPersonne
{
    ViewPersonne() {}
    void afficherPersonne(
        std::string prenom,
        std::string nom,
        std::string profession,
        int age
    ) const;
};

#endif // VIEW_PERSONNE_H

// ModelPersonne.hpp

#ifndef MODEL_PERSONNE_H
#define MODEL_PERSONNE_H

#include <string>

class ModelPersonne
{
    private:
        std::string prenom;
        std::string nom;
        std::string profession;
        int age;

    public:
        ModelPersonne(
            std::string unPrenom,
            std::string unNom,
            std::string uneProfession,
            int unAge
        ):
            prenom(unPrenom),
            nom(unNom),
            profession(uneProfession),
            age(unAge)
        {}

        virtual ~ModelPersonne() {}

        // Setters
        inline void setPrenom(std::string prenom) {
            this->prenom = prenom;
        }
        inline void setNom(std::string nom) {
            this->nom = nom;
        }
        inline void setProfession(std::string profession) {
            this->profession = profession;
        }
        inline void setAge(int age) {
            this->age = age;
        }

        // Getters
        inline std::string getPrenom() const {
            return prenom;
        }
        inline std::string getNom() const {
            return nom;
        }
        inline std::string getProfession() const {
            return profession;
        }
        inline int getAge() const {
            return age;
        }
};

#endif // MODEL_PERSONNE_H


// ControllerPersonne.hpp

#ifndef CONTROLLER_PERSONNE_H
#define CONTROLLER_PERSONNE_H

#include <string>

class ControllerPersonne
{
    private:
        ModelPersonne personne;
        ViewPersonne vue;

    public:
        ControllerPersonne(
            ModelPersonne personne,
            ViewPersonne vue
        ):
            personne(personne),
            vue(vue)
        {}

        // Setters
        inline void setPrenom(std::string prenom) {
            personne.setPrenom(prenom);
        }
        inline void setNom(std::string nom) {
            personne.setNom(nom);
        }
        inline void setProfession(std::string profession) {
            personne.setProfession(profession);
        }
        inline void setAge(int age) {
            personne.setAge(age);
        }

        // Getters
        inline std::string getPrenom() const {
            return personne.getPrenom();
        }
        inline std::string getNom() const {
            return personne.getNom();
        }
        inline std::string getProfession() const {
            return personne.getProfession();
        }
        inline int getAge() const {
            return personne.getAge();
        }
        void afficherPersonne() const;
};

#endif // CONTROLLER_PERSONNE_H


// ViewPersonne.cpp

#include <string>
#include <iostream>

void ViewPersonne::afficherPersonne(
    std::string unPrenom,
    std::string unNom,
    std::string uneProfession,
    int unAge
) const {
    std::cout << "Prénom: " << unPrenom << std::endl
        << "Nom: " << unNom << std::endl
        << "Profession: " << uneProfession << std::endl
        << "Âge: " << unAge << std::endl;
}


// ControllerPersonne.cpp

void ControllerPersonne::afficherPersonne() const {
    vue.afficherPersonne(
        personne.getPrenom(),
        personne.getNom(),
        personne.getProfession(),
        personne.getAge()
    );
}

// main.cpp

#include <string>

int main(){
    ModelPersonne unePersonne(
        "Jacques", "Baeur",
        "Artiste-Informaticien", 36
    );
    ViewPersonne uneVuePersonne; //();
    ControllerPersonne unControlleurPersonne(
        unePersonne,
        uneVuePersonne
    );
    unControlleurPersonne.afficherPersonne();
    return 0;
}

Bonne chance

2
JLesage Messages postés 33 Date d'inscription mercredi 14 novembre 2012 Statut Membre Dernière intervention 23 février 2024 5
8 nov. 2023 à 17:23

Merci pour les remarques très pertinentes, @mamiemando StatutModérateur . J'ai appris de nouvelles choses grâce à votre commentaire.

1
[Dal] Messages postés 6174 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 2 février 2024 1 083
3 nov. 2023 à 15:33

Salut JLesage,

Je pense que tu n'as pas posté le contenu de Controller_Personne.h et que tu as posté à la place celui de Controller_Personne.c

1
JLesage Messages postés 33 Date d'inscription mercredi 14 novembre 2012 Statut Membre Dernière intervention 23 février 2024 5
Modifié le 6 nov. 2023 à 21:08

J’ai les erreurs suivants dans mon code (je les ai numéroté parce qu’il y en a 3):

error 1: no matching function for call to ‘Model_Personne::Model_Personne()’;

error 2: no matching function for call to ‘Controller_Personne::Controller_Personne(Model_Personne&, View_Personne (&)())’;

error 3: no declaration matches ‘void View_Personne::afficherPersonne(std::string, std::string, std::string, std::string)’
0