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()
En info étudiant, vous devez vérifier null dans la destructor avant la suppression. (Pas lié à votre problème, mais important, aussi) –
l'auteur du livre a dit qu'il est sûr de supprimer le pointeur nul – trollpidor
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. –