-2

I have to understand why this program in C++ isn't working. There were many other errors but I corrected them.

#include <iostream>
using namespace std;

class X {
    public : 
    X(int a) : a(a) {}
    virtual void f(ostream& flot) const { flot << " X::f" << endl; }
    virtual void g() const = 0;

    private :
    int a;
};


class Z : public X {
    void h() const {cout << "Z::h" << endl;}
    public :
    Z() : X(0) {}
    void f(ostream& flot) const override { flot << "Z::f" << endl;}
    void g() const override  {cout << "Z::g" << endl;} 
};

void operator<< (ostream& flot, const Z& z ) { z.f(flot);}



int main() {
    Z z;
    cout << z << endl;
    Z z2();
    z2.h();
    X* x1;
    x1->f(cout);
    z.h();

}

You can't write cout << z << endl; because z does not exist as a normal object, is it correct? it is a kind of imaginary object ? at the contrary of z2 which is constructed and does exists. Can you tell me if I am right?

And I don't understand why the two last lines:

x1->f(cout);
z.h();

are not problematic. I thought that x1 does not exists (as z). So why can you call a method for x1?

And for z.h(), the only problem is that h is, here, in this context, private. But if it would have been inside the public part, it wouldn't be a problem. Why ??? Isn't z imaginary so you can't use any method on it?

Marine Galantin
  • 1,634
  • 1
  • 17
  • 28
  • `Z z2();` this probably doesn't do what you think it does. see [most vexing parse](https://stackoverflow.com/questions/1424510/most-vexing-parse-why-doesnt-a-a-work) – default May 23 '18 at 07:21
  • 2
    You are supposed to return `std::ostream` object back when you overload `operator <<`. Does this line `cout << z << endl;` compile? From my understanding, compiler would see `std::cout << z`, the result of this operation is `void`, and then it sees `void << std::endl`, which is obvious error. – Yksisarvinen May 23 '18 at 07:23
  • 2
    Did you try to compile this? Did you analyze the compile errors? What is the expected output? What is the actual output? – Robert Andrzejuk May 23 '18 at 07:41
  • 1
    Please explain what you understand by the concept imaginary. – Robert Andrzejuk May 23 '18 at 07:44
  • Welcome to Stack Overflow! It is difficult to offer solutions when the problem statement is simply, ["it doesn't work"](http://idownvotedbecau.se/itsnotworking/). Please [edit] your question to give a more complete description of what you expected to happen and how that differs from the actual results. See [ask] for hints on what makes a good explanation. – Toby Speight May 23 '18 at 10:55

3 Answers3

2
Z z;

This defines and constructs an object z of type Z. The default constructor is called.

cout << z << endl;

This calls operator<< for (cout, z), and then uses the return value of that to call operator<< for it and endl. The return value is void, so the second call cannot work. Your operator<< needs to return the output stream for this to work.

Z z2();

This defines a function z2 that takes no arguments and returns a Z. Not a variable, but not actually wrong itself.

z2.h();

At this point it's wrong, because z2 is a function and not an object. Try removing the parentheses, or changing the previous line to Z z2 = Z();.

X* x1;

This defines a variable x1 of type X*. It's uninitialized.

x1->f(cout);

This calls the function X::f on your uninitialized pointer, which is undefined behaviour. Read undefined behaviour as "could do anything, avoid".

z.h();

This tries to call the function h on z, but it's a private function. You'll get a compile error because it's private and not accessible from main context.

dascandy
  • 7,184
  • 1
  • 29
  • 50
1

To get cout to accept a Z object after the operator <<, overload the operator << to recognize an ostream object on the left and a Z on the right. The overloaded << operator function must then be declared as a friend of class Z.

The first error is solved by adding the following declaration to Z class:

friend ostream& operator<<(ostream& os, const Z& z);

On the other hand, if you want to invoke the method h on the instance z2 you have to make h public method, in your code it is private by default.

As a final note, you should receive a segmentation fault at the sentence:

x1->f(cout);

because the pointer x1 point to a non-allocated object.

Jorge
  • 137
  • 4
  • Why "must then be declared as a friend of class Z"? It does not use any private members of Z in this case. – Yksisarvinen May 23 '18 at 08:38
  • You are right, in this case, the friend declaration is not needed, the error was related to bad definition of the overloaded function (it should return ostream&) – Jorge May 23 '18 at 09:20
1

There is no "imaginary" object in C++. Either an object is created or it is not. There is nothing wring with Z z;. Since the object exists, there is no problem in using the function Z::h() once you make it public.

Z z2(); doesn't create an object as you intend, since it is parsed as a function taking no argument and returng an object of Z. This is, as pointed out in the first comment, the case of most vexing parse.

Regarding the cout, the operator << should be able to print stuff from your class. Hence, you need to make the operator a friend of your class.

Also, since x1 is declared but not initialized, you will have undefined behavior for x1->f();. Also, you can't even do something like X* x1 = new X(0); because X::g() is pure virtual, and the class X is an abstract base class.

The following code would run wothout issues:

#include <iostream>
using namespace std;

class X {
    public :
    X(int a) : a(a) {}
    virtual ~X() {}
    virtual void f(ostream& flot) const { flot << " X::f" << endl; }
    virtual void g() const {};

    private :
    int a;
};


class Z : public X {
    public :
    Z() : X(0) {}
    void f(ostream& flot) const override { flot << "Z::f" << endl;}
    void g() const override  {cout << "Z::g" << endl;}
    void h() const {cout << "Z::h" << endl;}
    friend ostream &operator<<(ostream &os, const Z &z);
};

ostream& operator<< (ostream& flot, const Z& z ) { z.f(flot); return flot;}

int main() {
    Z z;
    cout << z << endl;
    //Z z2();
    //z2.h();
    X * x1 = new X(0);
    x1->f(cout);
    z.h();
    delete x1;
    return 0;
}
mahesh
  • 1,028
  • 10
  • 24