PHPFixing
  • Privacy Policy
  • TOS
  • Ask Question
  • Contact Us
  • Home
  • PHP
  • Programming
  • SQL Injection
  • Web3.0

Tuesday, August 16, 2022

[FIXED] Why i can't call base class operator>> in derived class operator>>?

 August 16, 2022     c++, class, input, output, overloading     No comments   

Issue

Let's say we have 2 classes :

class base{

protected:
    char first_name;
public: 
    /// constructors , destructor, operator= overloading ...
    
    friend istream& operator >> (istream& in, base &client1) 
    {
        char f_name[1001];
        cout << "First Name: ";
        in >> f_name;
        client1=base(f_name); /// class parameterised constructor;
         
        return in;
    }
};

class derived: public base{

protected:
    char last_name[1001];
public: 
    /// constructors , destructor, operator= overloading ...
    
    friend istream& operator >> (istream& in, derived &client2) 
    {
        char l_name[1001], f_name[1001];
       
        in >> (base) client2; /// it's not working like it dose in operator<<..
        cout << "Last Name: ";
        is >> l_name;
        client2=derived(f_name, l_name); /// class parameterized constructor, 2 parameters because it use base constructor as well;
         
        return in;
    }
};

I overloaded some output operators (<<) and it seems to do fine every time i call the operator<< from base in derived operator<<.

I don't know if this works the same for operator<<, i tried something but it gives an error. When i call base class operator>> inside derived class operator>> it gives me error :

" no matching function for call to 'operator>>(std::istream&, abonament)'| "

Again, if i do the same thing in operator<< , it's working fine :

friend ostream& operator << (ostream& out, derived &client) 
    {
       
        out << (base) client; /// it's working;
       
        out << client.last_name;
         
        return in;
    }

Is it possible to call base class operator>> inside derived class operator>> > Why is this happening and how to solve it ? ( i hope i don't have to rewrite the same lines from base class operator>> again in derived class operator>> )


Solution

You have fallen prey to object slicing. You can fix the immediate problem by casting to a reference.

In

in >> (base) client2;

what's really happening is a new temporary Base is made from client2, discarding all of derived's added members. This is legal. The compiler gets upset because the temporary Base cannot be used as an argument to a base &client1 parameter. Temporary variables are just like they sound. They aren't around long, so taking a reference to one is a mistake the compiler is preventing you from making. If it were legal, the temporary variable would be modified by Base's >> operator and then immediately go out of scope before you could use what was read into it.

in >> (base&) client2;

does not slice and does not make a temporary variable. client2 is successfully updated. Unfortunately this work is thrown away when

client2=derived(f_name, l_name);

writes over it with the uninitialized variable l_name.

So more changes are needed.

Do not use constructors to completely recreate and reassign the objects you're reading into. Instead read directly into the object's member variables.

Example:

class base{

protected:
    char first_name[1001]; // need more than one character
public: 
    /// constructors , destructor, operator= overloading ...
    
    friend istream& operator >> (istream& in, base &client1) 
    {
        // char f_name[1001]; don't need. Read into member
        cout << "First Name: ";
        in >> client1.first_name; // read directly into member
        // client1=base(f_name); don't need. Work done above
         
        return in;
    }
};

class derived: public base{

protected:
    char last_name[1001];
public: 
    /// constructors , destructor, operator= overloading ...
    
    friend istream& operator >> (istream& in, derived &client2) 
    {
        //char l_name[1001], f_name[1001]; don't need. Use member variables
       
        in >> (base&) client2; // client was being sliced. explanatory link above
        //         ^ fixed with reference to allow polymorphism                             
        cout << "Last Name: ";
        in >> client2.last_name; // fixed typo. reading directly into member
        // client2=derived(f_name, l_name); don't need. Work done above
         
        return in;
    }
};

Side note: This is a misuse of inheritance. Effectively this is saying that a last name is-a first name. Which it isn't. Read up on the Liskov Substitution principle for a good rule to help determine when inheritance makes sense. Here's some starter reading: What is an example of the Liskov Substitution Principle?

Side Note: >> reads one whitespace-delimited token, one word, into the given char array. There are two problems here. The most important is it doesn't know when to stop. This is only partially mitigated by the 1001 character array. The user needs to type for a long time to overflow the buffer, but do not doubt that people will do it for fun or profit. Use std::string instead and that problem goes away. The second problem is the whole one word thing. This parser cannot handle Names like "Billy Bob" or "von Doom", and it's fortunate the owner of that last name is fictional as he's well-known to be unforgiving.



Answered By - user4581301
Answer Checked By - Gilberto Lyons (PHPFixing Admin)
  • Share This:  
  •  Facebook
  •  Twitter
  •  Stumble
  •  Digg
Newer Post Older Post Home

0 Comments:

Post a Comment

Note: Only a member of this blog may post a comment.

Total Pageviews

Featured Post

Why Learn PHP Programming

Why Learn PHP Programming A widely-used open source scripting language PHP is one of the most popular programming languages in the world. It...

Subscribe To

Posts
Atom
Posts
Comments
Atom
Comments

Copyright © PHPFixing