Say I have a Person class with a field string name. Now let's have a class Student deriving Person with a field int avgGrade. Both classes have the operator<< defined.
I want to be able to store in an array or similar structure elements of type Person, but also be able to store derived class objects in it. I'll be later traversing the elements and want to use the operator<< and actually call that specific object's definition for that operator, instead of always the base version of it.
How would I go about doing that? In what structure and what kind type of elements should I store?
Here's the current collection of classes:
Person.h:
#pragma once
#include <iostream>
class Person
{
private:
std::string name;
public:
Person();
Person(std::string);
friend std::ostream& operator<<(std::ostream& os, const Person& obj);
}
Person.cpp:
#include "Person.h"
Person::Person() : Person("default") { }
Person::Person(std::string name)
{
this->name = name;
}
std::ostream& operator<<(std::ostream& os, const Person& obj)
{
os << "Name: " << obj.name;
return os;
}
Student.h:
#pragma once
#include "Person.h"
#include <iostream>
class Student : Person
{
private:
double avgGrade;
public:
Student();
Student(const std::string cs, const double avg_grade);
friend std::ostream& operator<<(std::ostream& os, const Student& obj);
};
Student.cpp:
#include "Student.h"
Student::Student() : Student("default", 4) { }
Student::Student(const std::string cs, const double avg_grade)
: Person(cs),
avgGrade(avg_grade)
{
this->avgGrade = avg_grade;
}
std::ostream& operator<<(std::ostream& os, const Student& obj)
{
os << (Person)obj << std::endl;
os << "Average grade: " << obj.avgGrade;
return os;
}
Demo.cpp:
#include "Person.h"
#include "Student.h"
#include <iostream>
int main(int argc, char* argv[])
{
Person p("john");
Student s("johana", 5);
Person* arr[2];
arr[0] = &p;
arr[1] = &s; // Error: conversion to inaccessible base class "Person" is not allowed
std::cout << arr[0] << std::endl;
std::cout << arr[1] << std::endl;
return 0;
}