1

I am working with Qt 5.10 and I have to subclass QDatastream and I overload the operator << with an other class, like this :

class myDataStream:public QDataStream
{
public :
    myDataStream(QIODevice* device):QDataStream(device)
    {}
};

class data
{
public:
    data(double v):data_(v) {}
    double getData()  const {return data_;}

    void record(myDataStream& stream) const;

private:
    double data_;
};

void data::record(myDataStream &stream) const
{
    stream<<getData();
}

myDataStream &operator<<(myDataStream &stream, const data &d )
{
    stream<<d.getData(); //<------ Error here
    return stream;
}

I have this error :

> error: use of overloaded operator '<<' is ambiguous (with operand types 'myDataStream' and 'double')

When I remove the const operator behind data like this :

myDataStream &operator<<(myDataStream &stream, data &d )
    {
        stream<<d.getData();
        return stream;
    }

I don't have error. The operator<< doesn't change the class data ... doesn' it ? the getData() method is const.

I don't understand.

Someone to help me ?

vcloarec
  • 128
  • 8
  • Possible duplicate of [Meaning of 'const' last in a function declaration of a class?](https://stackoverflow.com/questions/751681/meaning-of-const-last-in-a-function-declaration-of-a-class) – eyllanesc Jun 29 '18 at 01:58
  • @eyllanesc, i don't think it is the same problem. I don't think the operator<< change the class data. The getData() method is const. – vcloarec Jun 29 '18 at 02:11
  • 1
    QDataStream is essentially a final class. Why are you aubclassing it? It wasn’t really designed to be subclassed. If you want a custom stream that hands off some implementation to `QDataStream`, you should use composition or private inheritance — your class is not a `QDataStream` anymore. Your stream operators can then be forwarding to QDS implementations as needed. The compiler is giving you a subtle hint about it. Of course there is a “fix” to the compiler error, but it only camouflages the fundamental design bug you have. – Kuba hasn't forgotten Monica Jun 29 '18 at 05:47
  • @Kuba Ober, but how to explain the error ? – vcloarec Jun 29 '18 at 10:15
  • @Kuba Ober : about the subclassing, I want to subclass QDataStream simply to specialize this class. Namely to doing somethings that QDataStream doesn't do and to keep all the fonctionnality af QDataStream. Why do you consider QDataStream is a final class ? Why can we don't subclass it ? I haven't seen anything about that – vcloarec Jun 29 '18 at 16:11
  • When minimizing — don’t stop. Keep removing stuff. Hopefully it will help you figure out exactly what happens, before I post an answer later. Take some pleasure in figuring it out — you’re certainly not done yet. E.g. you don’t need any constructors in `data`, you don’t need the `record` method, the private member (getData can return a 0.0) etc. Keep cutting it down and recompiling. – Kuba hasn't forgotten Monica Jun 29 '18 at 16:18
  • 1
    @vcloarec There are no hooks provided to specialize the base class. Your class violates the Liskov Substitution Principle and will utterly fail whenever its users end up accessing it through the base class type. This has nothing to do with Qt, of course. You’re making a class that behaves correctly only when accessed by the derived type — that’s not “specialization”, that’s pure breakage. There’s nothing stopping you from private inheritance. You can generically forward `operator<<` to use the `QDataStream` implementation when appropriate. So the public inheritance buys you nothing here. – Kuba hasn't forgotten Monica Jun 29 '18 at 16:24
  • And you definitely don’t want your class used by anyone taking a `QDataStream&` as input. In fact, the base class’s operators may not even work correctly — depending on what functionality you “specialized”. – Kuba hasn't forgotten Monica Jun 29 '18 at 16:25
  • Ok, thanks a lot for this explanations ! If I want to keep my subclassing, I overload the << operator like this : `QDataStream &operator<<(QDataStream &stream, const data &d ). Then I respect the Liskov Substitution Principle, do I ? --- For my curiosity, I continue searching about the error. A hint : when I remove the constructor, it 's working ... I keep thinking it is very strange .. – vcloarec Jun 29 '18 at 16:48
  • To "respect" LSP, you must make your class not be a `QDataStream`. It doesn't have to be. I don't understand your fixation on the data stream - it's an implementation detail. You can hide it, and implement your operators on your custom class - or maybe on the data stream if that's appropriate. You have to stop and ask yourself whether the customization belongs in the data stream, which is supposed to have a fixed, unalterable behavior, or perhaps in `QIODevice` - maybe a proxy/interposer I/O device that interfaces the real device to a generic `QDataStream`. – Kuba hasn't forgotten Monica Jul 01 '18 at 04:20
  • **Tell us exactly what functionality you're trying to add - it's likely that it doesn't belong where you think it does.** – Kuba hasn't forgotten Monica Jul 01 '18 at 04:21
  • @KubaOber : Finally, i will follow you advice and make QDataStream a composition of my class. Thanks a lot for your explanations that make me realize my wrong way and lead me to learn more about the best way to good conception !!! – vcloarec Jul 02 '18 at 21:09

1 Answers1

1

Finaly, I will follow the KubaOber advices (in comments of my questions) and make QDataStream a composition of my class instead of subclassing QDataStream.

Thanks to KubaOber for its advices !

vcloarec
  • 128
  • 8