Вы не совсем понимаете, в чем заключается ваша настоящая проблема - ndash; поэтому я предполагаю, что у вас возникли проблемы с получением желаемого результата для всей книги контактов ...
Во-первых, некоторые другие проблемы:
Нет смысла позволять contact_book
наследовать от entry
- книга содержит записей, она не одна. Кажется, что вы унаследовали только возможность переопределить функцию displaying
, чтобы использовать уже определенный класс operator<<
для entry
. Но это плохая причина для наследования. Вместо этого вы должны предоставить отдельную перегрузку operator<<
для вашей контактной книги:
std::ostream& operator(std::ostream& s, contact_book const& cb); // coming to later
Затем привыкните повторно использовать код там, где это необходимо; Я предполагаю, что getContents
должен выводить ту же строку, которая будет записана в std::cout
через operator<<
. Хорошо, тогда давайте получим прибыль от:
std::string entry::getContents()
{
std::ostringstream s;
s << *this;
return s.str();
}
Вам больше не нужно иметь его виртуальный (и не должен).
Лично я бы выбрал функцию по умолчанию для displaying
(это не очень хорошее имя, однако, вы должны предпочесть императивные формы 'display', возможно, даже лучше: 'printToStream' или просто 'printTo'):
void entry::printTo(std::ostream& s)
{
// output members to s
}
Тогда ваши наследующие классы могут использовать его повторно:
void phone_entry::printTo(std::ostream& s)
{
entry::printTo(s); // use parent's version first to print common data
// now append phone number to s...
}
Пользователи должны использовать operator<<
вместо функции printTo
. Это может быть хорошей идеей, чтобы защитить его (или даже частный).
Наконец вернемся к выводу книги контактов:
std::ostream& operator(std::ostream& s, contact_book const& cb)
{
// you want to output every entry? then do so:
for(auto& e : cb.contacts)
{
s << *e.second << std::endl;
// ^^^^^^^ map entries are of type std::pair<key_type const, mapped_type>
// ^ you stored pointers, operator<< accepts reference
}
}
Опять же, вы будете повторно использовать уже написанный код.
Последнее замечание: вы смешиваете классическую инициализацию (скобки) и равномерную инициализацию (фигурные скобки), один раз даже в одной строке (email_contact
):
entry(des), email{email_entry}
Лично я считаю, что пользовательский интерфейс в целом имеет некоторые веские аргументы, хотя способ, которым он был реализован в C ++, нарушен. Есть еще несколько проблем, мой «любимый» из них:
std::vector<int> v0{7}; // gives you a vector with 7 elements, all 0!!!
// with classic initialization:
std::vector<int> v1(7); // now clear, you WANT such a vector!
std::vector<int> v2({7}); // now clear, you want initializer list
Теперь вы можете следовать моим рассуждениям или нет (другие выбирают для UI, тем не менее, чтобы извлечь выгоду из преимуществ), но что бы вы ни решили - пожалуйста, сделайте это последовательно по всему файлу / проекту!