【问题标题】:How to overload operator << for derived classes using a shared base class?如何使用共享基类为派生类重载运算符 <<?
【发布时间】:2013-12-17 23:53:47
【问题描述】:

我试图在几个子类中重载operator&lt;&lt;。 我有一个名为Question 的超类,它有一个枚举值type 和一个字符串question。 该类的子类是TextQuestion、ChoiceQuestion、BoolQuestion 和ScaleQuestion。 TextQuestion 没有额外的数据字段。 ChoiceQuestion 有一个字符串向量,用于存储多项选择的可能性。 BoolQuestion 没有额外的数据字段。 ScaleQuestion 有两个整数值,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_;
};

现在,我正在尝试为所有这些子类重载 operatorthis example

于是我在超类中做了一个虚拟打印函数,重载了每个子类中的打印函数,超类中的operator&lt;&lt;调用了打印函数。

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_;
}  

我完全按照示例中的方式进行操作,但是当我输出我的问题时,它始终使用基类并仅输出 typequestion。编译器从不使用子类。

【问题讨论】:

  • @Till it is (查看Question中的decl)
  • 向我们展示打印方法和
  • 术语:重载意味着拥有两个可同时访问的同名函数,以及基于参数类型的自动编译时选择。 Override 意味着拥有一组具有相同参数类型的函数,其中一个由“正在执行”的对象的动态类型选择。
  • 我有一个经常被过度使用的水晶球,它告诉我你正在将派生类型对象切片到Question,然后再将它们发送到输出迭代器。您能否发布插入运算符的代码以及您对它的真实用法?漂亮吗?
  • @Potatoswatter:我认为你提出的问题比以前更不正确。您不能覆盖

标签: c++ inheritance operator-overloading virtual subclass


【解决方案1】:
  1. 只有virtual 函数允许根据对象的动态类型(给定基类的静态类型)进行分派。

  2. 只有非静态成员函数可以是virtual

  3. operator &lt;&lt; 不能是virtual,因为它不能是非静态成员函数,因为它的第一个参数必须是流。

  4. 您可以从接受对基类的引用的operator &lt;&lt; 调用虚函数。

    从非虚函数调用虚函数,以保留未被覆盖的接口方面,称为非虚习语

啊,我在第一次阅读时没有看到任何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.    

【讨论】:

    【解决方案2】:

    您不能在类中覆盖 operator&lt;&lt;,因为它不能是成员(您不能将 this 作为正确的操作数传递)。

    相反,在每个子类中重写一个虚拟print 函数,并根据它定义全局/纳米空间范围operator&lt;&lt;

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-04-04
      • 1970-01-01
      • 1970-01-01
      • 2015-07-20
      • 2012-01-15
      • 2018-12-01
      • 2011-08-06
      相关资源
      最近更新 更多