У меня такой рабочий код:
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
Как видите, у меня есть почти дублирующая реализация для <<
оператор в подклассе Tweeter
. Я должен был это сделать, поскольку, если я просто использую <<
реализация оператора унаследована от Person
, C ++ незаметно приводил Tweeter
экземпляр как Person
согласно подписи и вызову операторской функции Person::tostring()
вместо Tweeter::toString()
. Возможно ли иметь только одну реализацию <<
оператор, который может быть унаследован без переопределения и, следовательно, дублирования кода?
1 ответ
Да используйте виртуальный print()
функция.
PS. Я бы также сделал toString
используйте функцию виртуальной печати, чтобы сделать ее более эффективной.
class Person
{
// OTHER STUFF
virtual void print(std::ostream& target = std::cout) const
{
target << firstName << " ";
if (middleName != "") {
target << middleName << " ";
}
target << lastName;
}
std::string toString() const
{
std::stringstream stream;
this->print(str);
return stream.str();
}
friend std::ostream& operator<<(std::ostream& target, Person const& person)
{
person.print(target);
return target;
}
};
class Tweeter: public Person
{
// OTHER STUFF
// Don't need this any more: => std::string toString() const;
// Don't need this any more: => friend std::ostream& operator<< (std::ostream& target, Tweeter const & source);
virtual void print(std::ostream& target = std::cout) const override
{
target << "[" << to_string(id) << "] ";
Person::print(target);
target << " (" << twitterHandle << ")";
}
};
Спасибо. С
toString()
был только помощником для<<
На самом деле мне это больше не нужно после введения виртуальногоprint()
функции.— Ричард Нойманн