Thread: ABC, overloading ostream, printing out children

  1. #1
    Registered User zdq's Avatar
    Join Date
    Apr 2011
    Location
    Svalbard
    Posts
    5
    I want to print out the information for the children inside a vector, utilizing a shared pointer class that utilizes an Abstract base class. I cannot figure out the right way to overload it however. Maybe I should use some polymorph method for print..

    Error message
    Code:
    |25|error: 'std::ostream& shared_pointer_class::operator<<(std::ostream&, const Shared_class&)' must take exactly one argument|
    ||In function 'int main()':|
    |58|error: variable 'std::ofstream os' has initializer but incomplete type|
    |59|error: 'ostream_iterator' was not declared in this scope|
    |59|error: expected primary-expression before 'const'|
    |59|error: expected ';' before 'const'|
    |60|error: 'sp_out' was not declared in this scope|
    ||=== Build finished: 6 errors, 0 warnings ===|
    Code
    Code:
    #include <iostream>
    #include <vector>
    
    using namespace std;
    
    // ABC class
    class Shared_class
    {
    public:
      Shared_class(){}
      virtual void print() = 0;
      virtual ~Shared_class(){};
      virtual Shared_class * clone() = 0;
    private:
      double x,y;
    };
    
    // The shared pointer class
    class shared_pointer_class
    {
    public:
        shared_pointer_class(){ spc = 0;}
        shared_pointer_class(Shared_class * spc_in){ spc = spc_in; }
        ~shared_pointer_class(){};
        ostream& operator<<( ostream &os, const Shared_class & spc_in){ return os << spc_in.print(); } // Here is the error
    private:
        Shared_class * spc;
    };
    
    // Inherited classes
    class a : public Shared_class
    {
    public:
      a(double ix, double iy) : x(ix),y(iy) {}
      void print(){ cout << "(" << x << "," << y << ") " << endl; }
      a * clone(){ return new a(* this); }
    private:
      double x,y;
    };
    
    class b : public Shared_class
    {
    public:
       b(double ix, double iy, double iz) : x(ix),y(iy), z(iz) {}
      void print() { cout << "(" << x << "," << y << "," << z << ") " << endl;}
       b * clone(){ return new  b(* this); }
    private:
      double x,y,z;
    };
    
    int main()
    {
    
      vector<shared_pointer_class> shared_container;
      shared_container.push_back( shared_pointer_class(new a(4,10)) );
      shared_container.push_back( shared_pointer_class(new b(6,7,1)) );
    
      ofstream os("output.txt"); 
      ostream_iterator<const shared_pointer_class> sp_out(os,"\n"); 
      copy( shared_container.begin(), shared_container.end(), sp_out); 
      os.close(); // Error
    
      return 0;
    }
    Thanks in advance!

    I can declare the operator as friend to get rid of the two input arguments error but then I get this error:

    Code:
    In function 'std::ostream& operator<<(std::ostream&, const Shared_class&)':|
    25|error: passing 'const Shared_class' as 'this' argument of 'virtual void Shared_class::print()' discards qualifiers|
    |25|error: no match for 'operator<<' in 'os << ((const Shared_class*)spc_in)->Shared_class::print()'|
    
    + the same as above
    Last edited by zdq; 04-02-2011 at 09:35 AM.

  2. #2
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Firstly, print in shared_class should be const.
    Secondly, operator << in shared_pointer_class should be a friend.
    Thirdly, shared_pointer_class must delete its member variable pointer in the destructor.
    Fourthly, print in shared_class returns void. How do you expect to print void into a stream? Either it needs to return something that can actually be printed, or it needs to accept a stream as a parameter to output its contents to.
    Fifthly, there is no need to close a stream manually.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  3. #3
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,613
    Um, as long as you make print() a const method, then there should be no issue. Another potential problem is that you are using print() in a stream operation but print() doesn't return anything to print, exactly.

    There are several ways you could fix this. Here's one.
    Code:
    #include <iostream>
    #include <ostream>
    class A
    {
        public:
        friend std::ostream &operator<< (std::ostream &out, const A& obj);
        virtual void print(std::ostream &out) const { out << "printing A...\n"; }
    };
    class B : public A
    {
        public:
        void print(std::ostream &out) const { out << "printing B ...\n"; }
    };
    class C : public A
    {
        public:
        void print(std::ostream &out) const { out << "printing C ...\n"; }
    };
    std::ostream &operator<< (std::ostream &out, const A& itema)
    {
        itema.print(out);
        return out;
    }
    int main()
    {
        A foo;
        B bar;
        C quz;
        std::cout << foo << bar << quz;
    }

  4. #4
    Registered User zdq's Avatar
    Join Date
    Apr 2011
    Location
    Svalbard
    Posts
    5
    Thanks for the help guys/girls! Whiteflags or someone else can you please explain how you would call class A's print through another class D from main?

    I tried

    Code:
    class D
    {
    public:
       friend ostream& operator <<(ostream &os, A & obj);
    private:
        A * s;
    };
    
    ostream& operator <<(ostream &os, A & obj)
    {
        os << obj.print(&os);
        return os;
    }
    
    //
    Error message
    Code:
    ||=== OU4, Debug ===|
    |In function 'std::ostream& operator<<(std::ostream&, A&)':|
    |21|error: no matching function for call to 'A::print(std::ostream*)'|
    |9|note: candidates are: virtual void A::print(std::ostream&) const|
    ||=== Build finished: 1 errors, 0 warnings ===|

    Thanks in advance!

  5. #5
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    Lose the ampersand
    Code:
      os << obj.print(&os);
    I also fail to see why class D would need to declare an ostream<<() for class A as a friend.
    Right 98% of the time, and don't care about the other 3%.

    If I seem grumpy or unhelpful in reply to you, or tell you you need to demonstrate more effort before you can expect help, it is likely you deserve it. Suck it up, Buttercup, and read this, this, and this before posting again.

  6. #6
    Registered User zdq's Avatar
    Join Date
    Apr 2011
    Location
    Svalbard
    Posts
    5
    Hi!

    When I remove the ampersand i get:

    Code:
    ||In function 'std::ostream& operator<<(std::ostream&, A&)':|
    |39|error: no match for 'operator<<' in 'os << ((A*)obj)->A::print(((std::ostream&)((std::ostream*)os)))'
    ... and a lot of notes about candidates in basic_ostream.

    I need it so I can use the ofstream operator for the vector to create a file from it saving the coordinates. I think its doable this way.. somehow :-)

  7. #7
    C++ Junkie Mozza314's Avatar
    Join Date
    Jan 2011
    Location
    Australia
    Posts
    174
    Quote Originally Posted by zdq View Post
    Hi!

    When I remove the ampersand i get:

    Code:
    ||In function 'std::ostream& operator<<(std::ostream&, A&)':|
    |39|error: no match for 'operator<<' in 'os << ((A*)obj)->A::print(((std::ostream&)((std::ostream*)os)))'
    ... and a lot of notes about candidates in basic_ostream.

    I need it so I can use the ofstream operator for the vector to create a file from it saving the coordinates. I think its doable this way.. somehow :-)
    If it works with the ampersand it must be that A:: print takes a pointer. Can you show us the definition of A:: print you're using now?

  8. #8
    Registered User zdq's Avatar
    Join Date
    Apr 2011
    Location
    Svalbard
    Posts
    5
    The thing looks like this now:

    Code:
    #include <iostream>
    #include <fstream>
    #include <iterator>
    #include <vector>
    #include <string>
    
    using namespace std;
    
    class A // The AbstractBaseclass
    {
    public:
      A(){}
      virtual string print() const = 0;
    };
    
    class B : public A
    {
    public:
      B(double ix, double iy) : x(ix),y(iy) {}
      string print() const { return "printing B ...\n"; }
      private:
      double x,y;
    };
    
    class C : public A
    {
    public:
       C(double ix, double iy, double iz) : x(ix),y(iy), z(iz) {}
       string print() const { return "printing C ...\n"; }
    private:
      double x,y,z;
    };
    
    class D
    {
    public:
        D(){ spc = 0;}
        D(A * spc_in){ spc = spc_in; } // Takes a
        friend std::ostream &operator<< (std::ostream &out, const A& obj){ return out << obj.print(); }
        ~D(){  delete spc;};
    private:
        A * spc; // Stores pointers to the ABC
    };
    
    int main()
    {
      vector<D> shared_container;
      shared_container.push_back( D(new B(4,10)) );
      shared_container.push_back( D(new C(6,7,1)) );
    
    
      ofstream os;
      os.open("output.txt");
      ostream_iterator<const D> sp_out(os,"\n");
      copy( shared_container.begin(), shared_container.end(), sp_out); // <-- HERE BE ERROR!
    
      return 0;
    }
    I changed the void function print to string instead.. Seemed more reasonable. I'm using GNU GCC if that's of any help..

  9. #9
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by zdq
    I changed the void function print to string instead.. Seemed more reasonable.
    Except that now it is more of a "to_string" member function than "print".

    I would stick with this:
    Code:
    class A // The AbstractBaseclass
    {
    public:
      A(){}
      virtual void print(std::ostream& out) const = 0;
    };
    Then I would implement as a non-member non-friend function that has nothing to do with class D:
    Code:
    std::ostream& operator<<(std::ostream& out, const A& obj);
    Incidentally, I gather that it is very incomplete, but D would need a copy constructor and copy assignment operator implemented by you. I presume that you're basically trying to implement a simplified version of std::tr1::shared_ptr, right?
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  10. #10
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Code:
    friend std::ostream &operator<< (std::ostream &out, const A& obj){ return out << obj.print(); }
    I believe you have this part wrong.
    When you use std::copy, it will try to invoke operator << on all the objects stored in the vector.
    Since the vector stores objects of D, and you are outputting to an ofstream, the compiler would look for a function with signature:

    std::ofstream& operator << (ofstream& lhs, const D& rhs)

    But there is no such function. The closest one that is available is
    Code:
    friend std::ostream &operator<< (std::ostream &out, const A& obj){ return out << obj.print(); }
    So basically, you need to create an operator << that takes D objects as its right-hand-side parameter. Then you need to invoke print on D's spc.
    Last edited by Elysia; 04-03-2011 at 02:17 PM.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  11. #11
    Registered User zdq's Avatar
    Join Date
    Apr 2011
    Location
    Svalbard
    Posts
    5
    Quote Originally Posted by laserlight View Post
    Except that now it is more of a "to_string" member function than "print".

    I would stick with this:
    Code:
    class A // The AbstractBaseclass
    {
    public:
      A(){}
      virtual void print(std::ostream& out) const = 0;
    };
    Then I would implement as a non-member non-friend function that has nothing to do with class D:
    Code:
    std::ostream& operator<<(std::ostream& out, const A& obj);
    Incidentally, I gather that it is very incomplete, but D would need a copy constructor and copy assignment operator implemented by you. I presume that you're basically trying to implement a simplified version of std::tr1::shared_ptr, right?
    I'll try, thanks. I'm trying to understand how I can utilize a vector of a shared pointer class that uses a ABC and it's children. I'm not experienced in C++ (150 hours or so during the past few weeks) so I hadn't heard about tr1 but it seems promising if I understood smartpointers right. The code I post here just illustrates the problem I've been having for the past 24 hours.

    I think the combination of using vectors of a shared pointer class and ABC's can provide a huge benefit for solving complex problems (in my simple mind).

    Quote Originally Posted by Elysia View Post
    Code:
    friend std::ostream &operator<< (std::ostream &out, const A& obj){ return out << obj.print(); }
    I believe you have this part wrong.
    When you use std::copy, it will try to invoke operator << on all the objects stored in the vector.
    Since the vector stores objects of D, and you are outputting to an ofstream, the compiler would look for a function with signature:

    std:fstream& operator << (ofstream& lhs, const D& rhs)

    But there is no such function. The closest one that is available is
    Code:
    friend std::ostream &operator<< (std::ostream &out, const A& obj){ return out << obj.print(); }
    So basically, you need to create an operator << that takes D objects as its right-hand-side parameter. Then you need to invoke print on D's spc.
    Thanks for your reply and yes I think you are right that there is no such function. I'll give it a try. :-)
    Last edited by zdq; 04-03-2011 at 08:53 AM.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. C# Printing Problem
    By silverlight001 in forum C# Programming
    Replies: 0
    Last Post: 03-23-2009, 01:13 AM
  2. use <fstream> and ostream overloading together
    By mosu' in forum C++ Programming
    Replies: 3
    Last Post: 08-16-2006, 01:06 PM
  3. forks and children
    By suigeneris in forum C Programming
    Replies: 1
    Last Post: 01-22-2005, 05:48 AM
  4. issues using ostream while overloading []
    By Mr_Jack in forum C++ Programming
    Replies: 1
    Last Post: 01-12-2004, 12:00 PM
  5. Stupid compiler errors
    By ChrisEacrett in forum C++ Programming
    Replies: 9
    Last Post: 11-30-2003, 05:44 PM