C++ 运算符重载,用于使用抽象类<<

C++ Operator overloading for << with abstract class

本文关键字:抽象类 运算符 重载 用于 C++      更新时间:2023-10-16

这是我的头文件:

//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 类的运算符<<。有什么解决方案吗?另外,教授不希望我从头文件中更改任何内容!

编辑:以下是我实现运算符<<的方式:

// 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中的代码。

编辑2:所以我觉得我也应该分享我真实的测试代码:

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;

如果你真的想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);
}