2015-07-24 1 views
0

Mon programme a la structure suivante: classe de base est la classe de base, classe Grad hérite de base et la classe Pass_fail hérite de base. Classe Student_info gère simplement les pointeurs vers ces classes et crée l'objet approprié à l'exécution en fonction des besoins des utilisateurs. Le problème: les classes Core, Grad et Pass_fail ont une fonction virtuelle appelée grade(). Chaque classe calcule la note à sa manière. Lorsque le programme appelle grade() avec des objets Core ou Grad, cela fonctionne très bien. Mais lorsque le programme appelle grade() pour Pass_fail obj, le mécanisme virtuel ne fonctionne pas et la fonction Core.grade() est appelée.fonction virtuelle ne fonctionne pas pour 1 classe, mais travaille pour un autre

Classe de base:

class Core { 
    friend class Student_info; 
public: 
    Core() : midterm(0), final(0) { std::cerr << "Core obj created" << std::endl; } 
    Core(std::istream& is); 

    std::string name() const; 

    virtual std::istream& read(std::istream&); 
    virtual double grade() const; 
    virtual bool valid() const; 
    virtual bool did_req() const; 

    virtual ~Core() { } 
protected: 
    virtual Core* clone() const { return new Core(*this); } 
    std::istream& read_common(std::istream&); 
    std::istream& read_hw(std::istream&, std::vector<double>&); 
    double midterm, final; 
    std::vector<double> homework; 
private: 
    std::string n; 
}; 

Classe Grad:

class Grad : public Core { 
public: 
    Grad() : thesis(0) { std::cerr << "Grad obj created" << std::endl; } 
    Grad(std::istream& is); 

    double grade() const; 
    std::istream& read(std::istream&); 
    bool did_req() const; 
protected: 
    Grad* clone() const { return new Grad(*this); } 
private: 
    double thesis; 
}; 

Classe Pass_fail:

class Pass_fail : public Core 
{ 
public: 
    Pass_fail() { std::cerr << "Pass_fail obj created" << std::endl; } 
    Pass_fail(std::istream&); 
    std::istream& read(std::istream&); 

    double grade() const; 
    //bool did_req() const; 
protected: 
    Pass_fail* clone() { return new Pass_fail(*this); } 
}; 

fonction de qualité Pass_fail:

double Pass_fail::grade() const 
{ 
    std::cerr << "Pass_fail grade() function" << std::endl; 
    if (valid()) 
     return Core::grade(); 
    else 
    { 
     std::cerr << "Homework is empty" << std::endl; 
     return (midterm + final)/2.0; 
    } 
} 

classe Student_info (gère les pointeurs):

class Student_info { 
public: 
    Student_info(): cp(0) { } 
    Student_info(std::istream& is) : cp(0) { read(is); } 
    Student_info(const Student_info&); 
    Student_info& operator=(const Student_info&); 
    ~Student_info() { delete cp; } 

    std::istream& read(std::istream&); 
    bool valid() { return cp->valid(); } 
    bool did_req() { return cp->did_req(); } 

    std::string name() const 
    { 
     if (cp) return cp->name(); 
     else throw std::runtime_error("uninitialized student"); 
    } 
    double grade() const 
    { 
     if (cp) return cp->grade(); 
     else throw std::runtime_error("uninitialized student"); 
    } 
    static bool compare(const Student_info& s1, const Student_info& s2) 
    { 
     return s1.name() < s2.name(); 
    } 

private: 
    Core* cp; 
}; 

Un morceau de main():

... 
vector<Student_info> students; 
    Student_info record; 
... 
... 
while (record.read(cin)) 
    { 

     students.push_back(record); 
    } 
.... 
double final_grade = students[i].grade(); \\ the problem is here-> Core.grade() func is called instead of Pass_fail.grade() 
+0

En info étudiant, vous devez vérifier null dans la destructor avant la suppression. (Pas lié à votre problème, mais important, aussi) –

+0

l'auteur du livre a dit qu'il est sûr de supprimer le pointeur nul – trollpidor

+0

C'est un sujet difficile. Regardez ici: http://stackoverflow.com/q/6731331/1116364 Il est probablement sûr, mais vous ne pouvez pas être sûr à 100%. Le mieux serait de ne pas utiliser un pointeur brut. –

Répondre

0

J'ai trouvé l'erreur, clone() n'est pas const dans Pass_fail, c'est pourquoi le mécanisme virtuel n'a pas travail.

Student_info le constructeur de copie a donné chaque fois que j'ai fait students.push_back(record). Depuis clone() n'a pas été outrepassée dans Pass_fail classe, mal clone() a été cédée et par conséquent mal grade()