+ 1
Please help me fix the error in my code😋
I have attached a code, please go through it. The error is in the operator overloading part. For "a" (Apple), I overloaded the operator "<<" as a friend function and it works fine. But for "b" (Banana),I overloaded the same operator in member function way, but it's not working, it says that it can't find a correct match for that function. Thank you already 😋 https://code.sololearn.com/cTyW8LJPMfsA/?ref=app
13 odpowiedzi
+ 5
Line 38 doesn't actually look like line 24. Also the body of the two are different. No `Banana` object was accepted as argument whose properties were to be inserted to the output stream object.
The << operator for `Banana` class cannot be `const` so you'd need to remove that qualifier.
+ 3
Ipang If the operator is overloaded as a member function, it doesn't need another argument, it already refers to the "this" object. And why can't it be const?
Rishi If you overload the << operator as a member function for std::ostream, it becomes syntactic sugar for the function call
(*this).operator<<( std::ostream& )
where (*this) is the current "Banana" instance. As a consequence, you have to call the operator with a "Banana" object on the left side, and std::cout on the right:
b << std::cout << '\n';
Since this doesn't conform well with existing std::cout syntax, it is usually not done, and overloaded as a friend function instead.
In this case, the compiler is looking for either
std::ostream& std::ostream::operator <<( const Banana& );
which couldn't exist anyway, or
operator<<( const std::ostream&, const Banana& );
instead of the
std::ostream& Banana::operator<<( std::ostream& );
you defined, but did not call as per the syntax, hence the error.
+ 3
Ipang Sure, in that context you are of course correct and it can't be const, since it is no longer a member function, as stated by the error message. Thanks for clarifying. The approach of a friend function overload instead of a member function would be preferable anyway, in order to maintain the syntax.
+ 2
Shadow,
Sorry my bad : )
Honestly I am not familiar with definition of operator << overload as member function, that's why line 38 looked strange to me.
So I changed the operator << definition at line 38 as below, following after the signature of operator << definition for `Apple` class at line 24, with exception for the second argument type (`Banana` rather than `Apple`).
friend std::ostream& operator << ( std::ostream& out, const Banana& obj ) const
{
out << "Banana(" << obj.m_name << ", " << obj.m_colour << ')';
return out;
}
And there I got this error message
/Playground/file0.cpp:38:73: error: non-member
function std::ostream& operator<<(std:ostream&,
const Banana&) cannot have cv-qualifier
So that's what I meant by cannot be `const`
+ 2
Ipang Yes, it would work, but there is one pitfall:
https://code.sololearn.com/c7mNh0AmA8l5/?ref=app
Overloading only considers the static type of the function arguments when deciding which function to call. If you tried to dispatch an overloaded << operator via a base class pointer, and any derived class has its own overloaded insertion operator, e.g. because it has an additional field that needs to be printed, overload resolution would nonetheless always select the base class version. See the code above for an example of this scenario.
One way to get around this is by deferring the output to a protected/ private virtual function that is called from the base class operator overload, and derived classes that need a modified version overwrite the virtual function instead of defining a new overload. Code sample:
https://code.sololearn.com/c5TIXWw2Gwk6/?ref=app
+ 2
Ipang Feasible, but not recommended:
https://code.sololearn.com/cn6Z25JP66h8/?ref=app
+ 2
Ipang Yes, constructors are subject to access specifiers. Like any other protected member, protected constructors can only be accessed from within the class, or derived classes.
The change from reinterpret_cast<>() to static_cast<>() was somewhat arbitrary, but mostly because static_cast has more strict casting rules. There is no big difference in the end result.
+ 1
Shadow,
I was wondering, would it work, or be correct to define a non member operator << to accept a `Fruit` object and share use of it as friend in `Apple` and `Banana` class?
I mean, `Apple` and `Banana` both are based on `Fruit` class right? so I wonder if that was possible and/or correct.
+ 1
Shadow thank you so much, I didn't think that, you clarified my doubt. Great day ahead! 🥰
+ 1
Ipang thank you. About the question you asked Shadow , I think it's not possible because, even though they're based on fruit, still there different types. Just like two enums are different, they're different too. Also, overloaded operators cannot be inherited, I guess you know it already, but just in case ;).
PS: You just mentioned "shadow" but not tagged him/her. Notifications are only sent for tags (unless they followed this thread). We have to type "@" and then select the person to tag, if you can't find the person, start typing the name letter by letter and you'll get it ;)
+ 1
Shadow,
How can I make this operator able to access Apple::m_fibre ?
I gotta feeling it's impossible ...
https://code.sololearn.com/c8WP7AM7gvAb/?ref=app
+ 1
Shadow,
Please tell me about the `Fruit` function at line 29. Does that mean a constructor is inheritable by `protected` scope? I'm a bit lost here ...
Also I noticed you changed casting method from `reinterpret_cast` to `static_cast` for line 56. Why? and what's the difference?
+ 1
I get it Shadow,
Thanks