【问题标题】:how to use a friend cin/cout function from base templated interface in derived class [duplicate]如何在派生类中使用来自基本模板化接口的朋友 cin/cout 函数 [重复]
【发布时间】:2020-01-03 19:46:54
【问题描述】:

我已经定义了下一个具有 cin 和 cout 友元函数的模板化接口:

#ifndef IPRINTABLE_H
#define IPRINTABLE_H

#include <iostream>
using namespace std;

template <class T>
class IPrintable
{
public:
    virtual friend istream &operator>>(istream&, T&) = 0;
    virtual friend ostream &operator<<(ostream&, const T&) = 0;
};

#endif

我尝试将这些函数植入到这样的派生类中:

#ifndef DATE_H
#define DATE_H

#include "IPrintable.h"

class Date : public IPrintable<Date>
{
public:
    Date();
    Date(int, int, int);
    ~Date();

    void setDay(const int);
    void setMonth(const int);
    void setYear(const int);

    friend istream &operator>>(istream&, Date&);
    friend ostream &operator<<(ostream&, const Date&);

private:
    int day;
    int month;
    int year;
};

#endif

但我得到的只是一堆错误: 我尝试在互联网上搜索答案,但没有发现任何有用的信息,这就是为什么我请求您帮助解决这个问题。

我对在模板化界面中使用友元函数的继承概念不熟悉,所以我很可能在这里做错了。

提前谢谢你

附: 我该如何解决这个问题:

【问题讨论】:

  • 一般来说,friend's 不应该被使用。
  • 错误应该发布为文本,而不是图像(从输出选项卡的“构建顺序”列表复制)。
  • @JesperJuhl 我正在编写这个程序作为我的任务的一部分,我必须创建一个 IO 接口
  • @mega5800 “我正在编写这个程序作为作业的一部分” - 这有什么关系?

标签: c++ templates cin cout friend


【解决方案1】:

您不能创建friend 函数virtual,因为它不是成员函数。您要做的是:

template <class T>
class IPrintable
{
public:
    virtual void print(std::ostream&) const = 0;
    virtual void read(std::istream&) = 0;
    friend istream &operator>>(istream& in, IPrintable& p) {
        p.read(in);
        return in;
    }
    friend ostream &operator<<(ostream& out, const IPrintable& p) {
        p.print(out);
        return out;
    }
    virtual ~IPrintable() {}
};

class Date : public IPrintable<Date>
{
    // can even be private.
    void print(std::ostream &) const;
    void read(std::istream &);
};

那么,我们在做什么,为什么?在整个类层次结构中拥有朋友功能很复杂(实际上我自己不知道该怎么做)。因此,我们甚至不尝试实现这一点,而是解决这个问题。

我们在调用虚拟成员函数的基类中添加一个友元函数。既然是朋友,就可以调用这个私有函数。由于它的参数是一个引用,这个引用可以进一步绑定到基的所有子节点。

所以当一个孩子调用这个函数时(即通过std::cout &lt;&lt; Date{};),编译器将调用该函数并引用基类并调用它。在调用过程中,函数print 将被调用。因为它是虚拟的并且我们已经在子进程中覆盖了它,所以会调用覆盖并生成特定于子进程的输出。

【讨论】:

  • 所以我应该删除关键字friend 并尝试在派生类中解决它吗?
  • 正确的想法。看起来你已经写出了对模板的需求,所以我会删除它。
  • @user4581301 我正在编写这个程序作为我的任务的一部分,我必须创建一个 IO 接口
  • @mega5800 , n31459 正在演示有时称为虚拟朋友功能成语的东西。您保留这些函数,但如果处理打印的虚函数是 public,则它们不再需要成为朋友。
  • @mega5800 不再需要模板。流操作符只需要知道基类。流操作符调用的 virtual printread 函数会为您处理接口。
猜你喜欢
  • 2013-07-30
  • 2017-11-22
  • 1970-01-01
  • 2016-10-29
  • 2012-12-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-09-15
相关资源
最近更新 更多