C ++运算符重载<<与抽象类

时间:2018-04-22 21:52:46

标签: c++

以下是我的标题文件:

//Frame.h
#pragma once

class Frame {
    string frameName;
protected:
    double fileSize;
    vector<Attribute> attributes;
public:
    Frame(string f, double size, vector<Attribute> d) :frameName(f), fileSize(size), attributes(d) {}
    virtual ~Frame() {}
    string& GetFrameName() { return frameName; }
    Attribute& operator[](int);
    int size() { return attributes.size(); }
    virtual void Compress() = 0;
    friend ostream& operator<<(ostream&, Frame&);
};

// AudioFrame
#pragma once

class AudioFrame :public Frame {
    static const int RATES = 3;
    static constexpr double BITRATE[]{128,160,192};
    static constexpr double COMPRESSION_RATIO[]{11.1,9.1,7.1};
public:
    AudioFrame(string frameName, double fileSize, vector<Attribute> d) :Frame(frameName,fileSize, d) {}
    ~AudioFrame(){}
    void Compress();
    friend ostream& operator<<(ostream&, AudioFrame&);
};


//ImageFrame.h
#pragma once

class ImageFrame :public Frame {
    static const int BITS = 8;
    static constexpr double COMPRESSION_RATIO = 6.0;
    static constexpr double BITDEPTH_FACTOR[] {11.1,4.6,3.5,2.4,1.9,1.5,1.2,1.0};
public:
    ImageFrame(string fileName, double fileSize, vector<Attribute> d) :Frame(fileName, fileSize, d) {}
    ~ImageFrame(){}
    void Compress();
    friend ostream& operator<<(ostream&, ImageFrame&);
};

他们每个人都有一个**friend ostream& operator<<(ostream&, ImageFrame&);** 但是当我这样做时

ImageFrame test;
cout << test << endl;

仅调用Frame类的运算符<<。对此有何解决方案? 另外,教授不希望我改变头文件中的任何内容!

修改 这是我如何实现运算符&lt;&lt;:

// code from AudioFrame.cpp
ostream& operator<<(ostream& os, AudioFrame& obj) {
    os << "AudioFrame" << endl;
    os << "Name = " << obj.GetFrameName() << endl;
    for (unsigned int i = 0; i < obj.attributes.size(); i++) {
        os << "\tBandwidth #" << i << ": " << obj.attributes[i] << endl;
    }

    return os;
}

// code from ImageFrame.cpp
ostream& operator<<(ostream& os, ImageFrame& obj) {
    os << "ImageFrame" << endl;
    os << "Name = " << obj.GetFrameName() << endl;
    for (unsigned int i = 0; i < obj.attributes.size(); i++) {
        os << "\tResolution #" << i << ": " << obj.attributes[i] << endl;
    }

    return os;
}

// code from Frame.cpp
ostream& operator<<(ostream& os, Frame& obj) {
    return os;
}

但是当我运行测试代码时,只运行Frame.cpp中的代码。

EDIT2: 所以我觉得我也应该分享我真正的测试代码:

int type;
deque<Frame*> frames; // all frames are stored here
// user is promoted a console menu for selecting a frame type (ImageFrame or AudioFrame)

if (type == 1)
    frames.push_back(new AudioFrame(...));
else
    frames.push_back(new ImageFrame(...));

// now when i need to print all frames i do
for (unsigned int i = 0; i < frames.size(); i++)
    cout << *(frames[i]) << endl;

1 个答案:

答案 0 :(得分:2)

如果你真的希望cout << *(frames[i]) << endl;以多态方式发送,而你真的无法改变标题,那么你别无选择,只能依靠动态输入。

ostream& operator<<(ostream& stream, Frame& frame) {
  AudioFrame* as_audio_frame = dynamic_cast<AudioFrame*>(&frame);
  ImageFrame* as_image_frame = dynamic_cast<ImageFrame*>(&frame);

  if(as_audio_frame) {
    return stream << *as_audio_frame;
  }

  if(as_image_frame) {
    return stream << *as_image_frame;
  }

   //normal frame code
}

然而,这是可怕的代码,并且表明在标题中非常需要一些重组。所以我怀疑你的任务代表性有问题。

编辑,实际上,有一种非常热闹的过度设计......

class FrameAdapterInterface {
public:
  virtual ~FrameAdapterInterface() {};

protected:
  virtual std::ostream print(std::ostream&) = 0;
  friend ostream& operator<<(ostream&, FrameAdapterInterface &);
};

template<typename FRAME_T>
class AdapatedFrameType : public FrameAdapterInterface {
  FRAME_T data_;
public:
  template<typename... ARGS_T>
  AdapatedFrameType(ARGS_T&&... args)
    : data_(std::forward<ARGS_T>(args)...) {}

  ostream& print(std::ostream& stream) override {
    return stream << data_; 
  }
};

ostream& FrameAdapterInterface::operator<<(ostream& stream, FrameAdapterInterface& frame) {
  return frame.print(stream);
}