My program has the following structure: class Core is the base class, class Grad inherits Core and class Pass_fail inherits Core. Class Student_info just manages pointers to these classes and create appropriate object at the run-time according to users' needs. The problem: classes Core, Grad and Pass_fail have a virtual function called grade(). Every class calculates the grade in its own way. When the program calls grade() with Core or Grad objects, it works just fine. But when the program calls grade() for Pass_fail obj, virtual mechanism doesn't work and instead Core.grade() function is called.
Class Core:
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;
};
Class 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;
};
Class 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); }
};
Pass_fail grade function:
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;
}
}
Class Student_info (manages pointers):
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;
};
A piece of 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()