Search code examples
c++inheritanceoperator-overloadingvirtualostream

C++ OOP overloading ostream problem at printing


This is my code:

#include <iostream>
#include <cstring>

using namespace std;

class ObiectCosmic{
    protected:
        char* nume;
        float raza;
        float masa;
    public:
        ObiectCosmic(char* nume = "", float raza = 0.0, float maza = 0.0);
        virtual ~ObiectCosmic();
};

ObiectCosmic::ObiectCosmic(char* nume, float raza, float masa){
    this->nume = new char[strlen(nume) + 1];
    strcpy(this->nume, nume);
    this->raza = raza;
    this->masa = masa;
}

ObiectCosmic::~ObiectCosmic(){
    delete[] nume;
}

class Planeta: public ObiectCosmic{
    private:
        float perioadaRotatie;
    public:
        Planeta(char* nume = "", float raza = 0.0, float masa = 0.0, float perioadaRotatie = 0.0);
        ~Planeta();
        friend ostream& operator<<(ostream& os, const Planeta& p);
};

Planeta::Planeta(char* nume, float raza, float masa, float perioadaRotatie): ObiectCosmic(nume, raza, masa){
    this->perioadaRotatie = perioadaRotatie;
}

Planeta::~Planeta(){}

ostream& operator<<(ostream& os, const Planeta& p){
    os << "Nume: " << p.nume << ", raza: " << p.raza << "masa: " << p.masa << ", rotatie: " << p.perioadaRotatie << endl;
    return os;
}

class Stea: public ObiectCosmic{
    private:
        float stralucire;
    public:
        Stea(char* nume = "", float raza = 0.0, float masa = 0.0, float stralucire = 0.0);
        ~Stea();
        friend ostream& operator<<(ostream& os, const Stea& s);
};

Stea::Stea(char* nume, float raza, float masa, float stralucire): ObiectCosmic(nume, raza, masa){
    this->stralucire = stralucire;
}

Stea::~Stea(){}

ostream& operator<<(ostream& os, const Stea& s){
    os << "Nume: " << s.nume << ", raza: " << s.raza << "masa: " << s.masa << ", stralucire: " << s.stralucire << endl;
    return os;    
}

int main(){
    Stea s("Soare", 123123.54, 3543454325.2, 343434.132);
    Planeta p("Pamant", 34132.12, 567546.234, 3545.13);
    Planeta p2;
    
    ObiectCosmic* obiecte[] = {
        &s,
        &p,
        &p2
    };

    for(int i = 0; i < sizeof(obiecte) / sizeof(ObiectCosmic*); i++)
        cout << obiecte[i] << endl;

    return 0;       
}

He is printing the adress of objects instead of what i wrote.

I tried with cout << *obiecte[i] << endl;, but i have an error.

10.cpp:79:14: error: no match for 'operator<<' (operand types are 'std::ostream' {aka 'std::basic_ostream<char>'} and 'ObiectCosmic')
   79 |         cout << *obiecte[i] << endl;
      |         ~~~~ ^~ ~~~~~~~~~~~
      |         |       |     
      |         |       ObiectCosmic
      |         std::ostream {aka std::basic_ostream<char>} 
In file included from C:/msys64/mingw64/include/c++/12.2.0/iostream:39

Solution

  • There are several problems with your code.

    For starters string literals in C++ have types of constant character arrays.

    So for example instead of this constructor declaration

    Stea(char* nume = "", float raza = 0.0, float masa = 0.0, float stralucire = 0.0);
    

    you have to write

    Stea( const char* nume = "", float raza = 0.0, float masa = 0.0, float stralucire = 0.0);
    

    Numerical data members have the the float. So you need to call the constructors providing constants of the type float like for example

    Stea s( "Soare", 123123.54f, 3543454325.2f, 343434.132f );
    Planeta p( "Pamant", 34132.12f, 567546.234f, 3545.13f );
    

    Otherwise the compiler can issue a warining relative to narrowing conversion. Otherwise declare the data members as having the type double.

    You declared a friend function that accepts a reference to the type Stea

    friend ostream& operator<<(ostream& os, const `Stea`& s);
    

    but trying to call it passing references to objects of the type Planeta. So the compiler issues an error that there is no such a function.

    To make the friend operator << "virtual" you should declare it like

    friend ostream& operator<<(ostream& os, const Planeta& s);
    

    and within it call a virtual function of an object of the corresponding type.

    Here is a demonstration program.

    #include <iostream>
    #include <string>
    #include <cstring>
    
    using namespace std;
    
    class ObiectCosmic
    {
    protected:
        char *nume;
        float raza;
        float masa;
    
        virtual std::ostream & out( std::ostream &os = std::cout ) const 
        {
            return os << "Nume: " << nume << ", raza: " << raza << ", masa: " << masa;
        }
    public:
        ObiectCosmic( const char *nume = "", float raza = 0.0, float maza = 0.0 );
        virtual ~ObiectCosmic();
        friend ostream & operator <<( ostream &os, const ObiectCosmic &p );
    
    };
    
    ObiectCosmic::ObiectCosmic( const char *nume, float raza, float masa ) 
    {
        this->nume = new char[strlen( nume ) + 1];
        strcpy( this->nume, nume );
        this->raza = raza;
        this->masa = masa;
    }
    
    ObiectCosmic::~ObiectCosmic() 
    {
        delete[] nume;
    }
    
    class Planeta : public ObiectCosmic
    {
    protected:
    std::ostream &out( std::ostream &os = std::cout ) const override
    {
        return  ObiectCosmic:: out( os ) << ", perioada rotatie: " << perioadaRotatie;
    }
    
    private:
        float perioadaRotatie;
    public:
        Planeta( const char *nume = "", float raza = 0.0, float masa = 0.0, float perioadaRotatie = 0.0 );
        ~Planeta();
    };
    
    Planeta::Planeta( const char *nume, float raza, float masa, float perioadaRotatie ) : ObiectCosmic( nume, raza, masa ) {
        this->perioadaRotatie = perioadaRotatie;
    }
    
    Planeta::~Planeta() {}
    
    ostream &operator<<( ostream &os, const ObiectCosmic &p ) {
        return p.out( os );
    }
    
    class Stea : public ObiectCosmic
    {
    private:
        float stralucire;
    public:
        Stea( const char *nume = "", float raza = 0.0, float masa = 0.0, float stralucire = 0.0 );
        ~Stea();
    };
    
    Stea::Stea( const char *nume, float raza, float masa, float stralucire ) : ObiectCosmic( nume, raza, masa ) {
        this->stralucire = stralucire;
    }
    
    Stea::~Stea() {}
    
    int main()
    {
        Stea s( "Soare", 123123.54f, 3543454325.2f, 343434.132f );
        Planeta p( "Pamant", 34132.12f, 567546.234f, 3545.13f );
        Planeta p2;
    
        ObiectCosmic *obiecte[] = {
            &s,
            &p,
            &p2
        };
    
        for (size_t i = 0; i < sizeof( obiecte ) / sizeof( *obiecte ); i++)
            cout << *obiecte[i] << endl;
    }
    

    The program output is

    Nume: Soare, raza: 123124, masa: 3.54345e+09
    Nume: Pamant, raza: 34132.1, masa: 567546, perioada rotatie: 3545.13
    Nume: , raza: 0, masa: 0, perioada rotatie: 0