I have the following working code:
person.h
#ifndef PERSON_H
#define PERSON_H
#include <iostream>
#include <string>
class Person {
private:
std::string firstName;
std::string middleName;
std::string lastName;
public:
Person() = default;
Person (std::string pFirstName, std::string pMiddleName, std::string pLastName);
Person (std::string pFirstName, std::string pLastName);
std::string getFirstName();
void setFirstName(std::string pFirstName);
std::string getLastName() const;
void setLastName(std::string pLastName);
std::string toString() const;
friend std::ostream& operator<<(std::ostream& target, Person const & person);
};
#endif
person.cpp
#ifndef __person__
#define __person__
#include <iostream>
#include <string>
#include "person.h"
using std::string;
using std::ostream;
Person::Person (string pFirstName, string pMiddleName, string pLastName)
: firstName(pFirstName), middleName(pMiddleName), lastName(pLastName)
{
}
Person::Person (string pFirstName, string pLastName)
: firstName(pFirstName), middleName(""), lastName(pLastName)
{
}
string Person::getFirstName ()
{
return firstName;
}
void Person::setFirstName (string pFirstName)
{
firstName = pFirstName;
}
string Person::getLastName () const
{
return lastName;
}
void Person::setLastName (string pLastName)
{
lastName = pLastName;
}
string Person::toString () const
{
if (middleName == "")
return firstName + " " + lastName;
return firstName + " " + middleName + " " + lastName;
}
ostream& operator<< (ostream& target, Person const & source)
{
target << source.toString();
return target;
}
#endif
tweeter.h
#ifndef TWEETER_H
#define TWEETER_H
#include <string>
#include "person.h"
class Tweeter
: public Person
{
private:
static int gid;
int id;
std::string twitterHandle;
public:
Tweeter(std::string pFirstName, std::string pMiddleName, std::string pLastName, std::string pTwitterHandle);
Tweeter(std::string pFirstName, std::string pLastName, std::string pTwitterHandle);
std::string toString() const;
friend std::ostream& operator<< (std::ostream& target, Tweeter const & source);
};
#endif
tweeter.cpp
#ifndef __tweeter__
#define __tweeter__
#include <iostream>
#include "tweeter.h"
using std::ostream;
using std::string;
using std::to_string;
int Tweeter::gid = 0;
Tweeter::Tweeter(string pFirstName, string pMiddleName, string pLastName, string pTwitterHandle)
: Person(pFirstName, pMiddleName, pLastName), id(gid), twitterHandle(pTwitterHandle)
{
gid++;
}
Tweeter::Tweeter(string pFirstName, string pLastName, string pTwitterHandle)
: Tweeter(pFirstName, "", pLastName, pTwitterHandle)
{
}
string Tweeter::toString() const
{
return "[" + to_string(id) + "] " + Person::toString() + " (" + twitterHandle + ")";
}
ostream& operator<< (ostream& target, Tweeter const & source)
{
target << source.toString();
return target;
}
#endif
As you can see, I have a nearly duplicate implementation for the << operator in the subclass Tweeter. I had to do that, since, if I just use the << operator implementation inherited from Person, C++ would silently cast the Tweeter instance as Person as per the operator function's signature and call Person::tostring() instead of Tweeter::toString().
Is it possible to just have one implementation of the << operator that can be inherited without override and thusly code duplication?
operator<<call a virtual function on the object. Then you only need to define it for person (not for Tweeter). This will make it print the most derived version. \$\endgroup\$