我正在尝试在多个子类中重载operator<<
。
我有一个叫做 Question 的超类,它有一个枚举值 type ,还有一个字符串 question 。
该类的子类是 TextQuestion,ChoiceQuestion,BoolQuestion和ScaleQuestion。 TextQuestion 没有其他数据字段。 ChoiceQuestion 有一个字符串向量,用于存储多项选择的可能性。 BoolQuestion 没有其他数据字段。 ScaleQuestion 有两个int值, low _ 和 high _ ,用于比例。
class Question {
public:
enum Type{TEXT, CHOICE, BOOL, SCALE};
Question():
type_(), question_() {}
Question(Type type, std::string question):
type_(type), question_(question) {}
friend std::ostream& operator<<(std::ostream& out, const Question& q);
virtual void print(std::ostream& out) const;
virtual ~Question();
private:
Type type_;
std::string question_;
};
class TextQuestion: public Question {
public:
TextQuestion():
Question() {}
TextQuestion(Type type, std::string question):
Question(type, question) {}
void print(std::ostream& out) const;
virtual ~TextQuestion();
};
class ChoiceQuestion: public Question {
public:
ChoiceQuestion():
Question(), choices_() {}
ChoiceQuestion(Type type, std::string question, std::vector<std::string> choices):
Question(type, question), choices_(choices) {}
void print(std::ostream& out) const;
virtual ~ChoiceQuestion();
private:
std::vector<std::string> choices_;
};
class BoolQuestion: public Question {
public:
BoolQuestion():
Question() {}
BoolQuestion(Type type, std::string question):
Question(type, question) {}
void print(std::ostream& out) const;
virtual ~BoolQuestion();
};
class ScaleQuestion: public Question {
public:
ScaleQuestion():
Question(), low_(), high_() {}
ScaleQuestion(Type type, std::string question, int low = 0, int high = 0):
Question(type, question), low_(low), high_(high) {}
void print(std::ostream& out) const;
virtual ~ScaleQuestion();
private:
int low_, high_;
};
现在,我正在尝试重载运算符&lt;&lt;对于所有这些子类,我尝试使用this example
所以我在超类中创建了一个虚拟打印函数,重载了每个子类中的print函数,超类中的operator<<
调用了print函数。
std::ostream& operator<<(std::ostream& out, const Question& q) {
q.print(out);
return out;
}
void Question::print(std::ostream& out) const {
std::string type;
switch(type_) {
case Question::TEXT:
type = "TEXT";
break;
case Question::CHOICE:
type = "CHOICE";
break;
case Question::BOOL:
type = "BOOL";
break;
case Question::SCALE:
type = "SCALE";
break;
}
out << type << " " << question_;
}
void TextQuestion::print(std::ostream& out) const {
Question::print(out);
}
void ChoiceQuestion::print(std::ostream& out) const {
Question::print(out);
out << std::endl;
int size(get_choices_size());
for (int i = 0; i < size; ++i) {
out << choices_[i] << std::endl;
}
}
void BoolQuestion::print(std::ostream& out) const {
Question::print(out);
}
void ScaleQuestion::print(std::ostream& out) const {
Question::print(out);
out << " " << low_ << " " << high_;
}
我在示例中完全按照这样做,但是当我输出我的问题时,它总是使用基类并仅输出类型和问题。编译器从不使用子类。
答案 0 :(得分:6)
virtual
函数允许根据对象的动态类型进行调度(给定基类的静态类型)。virtual
。operator <<
不能是virtual
,因为它不能是非静态成员函数,因为它的第一个参数必须是流。您可以从operator <<
调用虚拟函数,该函数接受对基类的引用。
从非虚函数调用虚函数,以保留未被覆盖的界面方面,称为非虚拟习语。
啊,我在第一次阅读时没有看到任何virtual
,但现在我做到了。如果你没有得到预期的子类行为,可能的罪魁祸首就是切片,你可以在其中创建一个基类类型的对象,并从子类对象中为它赋值。
TextQuestion q( "What is hello, world?" ); // Original object
Question & qr( q ); // Reference, not another object
Question q2( q ); // Base class object with copied subset (slice) of data.
std::cout << q << '\n'; // Observe subclass behavior.
std::cout << qr << '\n'; // Observe subclass behavior due to dynamic typing.
std::cout << q2 << '\n'; // Observe superclass behavior due to slicing.
答案 1 :(得分:1)
您无法覆盖类中的operator<<
,因为它不能是成员(您无法将this
作为正确的操作数传递。)
相反,在每个子类中重写虚拟print
函数,并根据它定义global / nanespace作用域operator<<
。