【问题标题】:Overload operator in subclass子类中的重载运算符
【发布时间】:2013-10-23 00:06:57
【问题描述】:

旅游和导游。导览游扩展了旅游课程。我正在重载旅游课程中的 > 运算符。

我的旅行班看起来像

#include <iostream>
#include <vector>
#include "Customer.h"

using namespace std;

class Tour {

protected:
    string id;
    string description;
    double fee;
    vector<string> customerList;

public:
    Tour();
    Tour(string idVal, string descriptionVal, double feeVal);
    string getId();
    string getDescription();
    double getFee();
    double getTotalForTour();
    virtual void addCustomer(string cust);
    vector<string> getCustomers();
    virtual void display();

    friend ostream& operator<< (ostream &out, Tour &cust);
    friend istream& operator>> (istream &in, Tour &cust);
};

那么我的导览是这样的,

#include <iostream>
#include "Tour.h"
#include "SimpleDate.h"

using namespace std;

class GuidedTour : public Tour {

private:
    SimpleDate* date;
    string guideName;
    int maxNumTourists;

public:
    GuidedTour();
    GuidedTour(string idVal, string descriptionVal, double feeVal, SimpleDate* dateVal, string guideNameVal, int maxNumTouristsVal);
    virtual void addCustomer(string cust);
    SimpleDate* getDate();
    void display();

    friend ostream& operator<< (ostream &out, GuidedTour &cust);
    friend istream& operator>> (istream &in, GuidedTour &cust);
};

我想在子类上以不同的方式重载这些运算符来做其他事情。

我有一个包含游览和导游的向量。

当我遍历向量并执行以下操作时,

for (unsigned int i = 0; i < tourListVector.size(); i++) {

    cout << *tourListVector[i];
}

即使对象是导览,它也始终执行游览中指定的操作。

你能帮忙吗?

【问题讨论】:

  • this 可能会有所帮助
  • 从您的友元基类运算符调用的虚拟read(std::stream&amp;)write(std::ostream&amp;) 将消除在派生类中重写运算符的需要。派生覆盖readwrite(如果需要,甚至可以直接调用基类作为其派生功能的一部分)。
  • 你能解释一下吗?抱歉,我对 C++ 很陌生
  • @Archie Any good C++ book 将解释这一点以及更多内容。
  • @Archie follow the link in Ivaylo's comment above。 Loki 在该问题中的回答与您将在 SO 答案的有限空间中看到的一样好。

标签: c++ operator-overloading


【解决方案1】:

您几乎在做正确的事,但并不完全正确。让我们先来看输出案例——输入案例的工作原理是一样的。

首先,你应该声明一个

virtual void write(std::ostream&) const;

基类中的成员函数。实现可能类似于:

void Tour::write(std::ostream& os) const
{
    os << "ID: " << id << std::endl;
    os << "Description: " << description << std::endl;
    // etc
}

我认为这是您当前在 operator&lt;&lt;(ostream&amp;, Tour&amp;) 中的那种代码。然后你需要在你的派生类中重载它——也许像

void GuidedTour::write(std::ostream& os) const
{
    Tour::write(os); // Write out base Tour info first
    os << "Guide Name: " << guideName << std::endl;
    // etc
}

之后,您可以为Tours 声明一个免费(即非成员)operator&lt;&lt; 重载,它会调用您的write() 成员函数,例如

std::ostream& operator<<(std::ostream& os, const Tour& tour)
{
    tour.write(os);
    return os;
}

例如。

解释:忘记你现在的operator&lt;&lt;是朋友这一事实;在这种情况下它没有任何影响。相反,假设您有两个重载的非成员函数,称为

void do_something(Tour& t); // (a)
void do_something(GuidedTour& gt); // (b)

由于您的 tourListVector 包含(我假设)Tour* 指针,如果您要循环遍历向量并在每个元素上调用 do_something(),编译器将只能匹配上面的函数 (a)。那是因为它无法知道某些Tour* 指针对于给定的程序运行可能实际上指向GuidedTour 实例。为了像这样进行运行时调度,您需要使用虚函数。

旁白:(我知道这是示例代码,但如果您是 C++ 新手,那么值得指出以防万一您不知道 :-))

因为您使用的是Tour* 指针,所以您应该为您的基类定义一个虚拟析构函数。如果您不这样做,编译器将不会知道当您在Tour* 上调用delete 时它可能需要破坏GuidedTour 类的所有成员。实际上,如果您的类包含任何其他虚函数,则将析构函数设为虚函数通常是一种很好的做法,只是为了以后避免潜在的问题。

另外,请不要将using namespace std; 放在头文件中:-)

【讨论】:

    【解决方案2】:

    如果我理解正确,您的向量中有指针。所以你应该使用关键字virtual。并阅读 C++ 中的虚拟方法。

    【讨论】:

    • 如果我使用 virtual 我得到错误 Tour.h:36: error: virtual functions cannot be friends
    • @Archie:你重写了一个print 虚函数并让operator&lt;&lt; 调用它。
    猜你喜欢
    • 2021-07-10
    • 1970-01-01
    • 2021-05-14
    • 2015-03-08
    • 1970-01-01
    • 1970-01-01
    • 2019-09-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多