假设我有一个带有字段字符串名称的Person类。现在让我们让一个学生派生一个具有 int avgGrade 字段的人。两个类都有运算符<<定义
我希望能够存储Person类型的数组或类似结构元素,但也能够在其中存储派生类对象。我稍后会遍历这些元素,并希望使用运算符<<并实际上为该运算符调用该特定对象的定义,而不是始终为其基本版本。
我该怎么做呢?我应该在什么结构和什么类型的元素存储?
这是当前的课程集合:
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;
}
答案 0 :(得分:3)
这类问题的一般解决方案是声明:
inline std::ostream& operator<<(std::ostream& str, const Base& o)
{
o.print(str);
return str;
}
作为非成员函数,然后:
virtual void print(std::ostream& str);
<{1>}中的,并根据需要覆盖Base
。 (Derived
版本可以从Derived
开始调用基本版本。)
您对Base::print(str);
的声明没有问题,但您可以使用以下字符打印元素:
array
初始化数组的问题是,默认情况下,基类是私有的。修正:
std::cout << *arr[0] << std::endl;
std::cout << *arr[1] << std::endl;