class Port
{
private:
char * brand;
char style[20]; // i.e., tawny, ruby, vintage
int bottles;
public:
Port(const char * br = "none", const char * st = "none", int b = 0);
Port(const Port & p); // copy constructor
virtual ~Port() {delete[] brand; }
Port & operator=(const Port & p);
Port & operator+=(int b); // adds b to bottles
Port & operator-=(int b); // subtracts b from bottles, if
int BottleCount() const { return bottles; }
virtual void Show() const;
friend ostream & operator<<(ostream & os, const Port & p);
};
class VintagePort : public Port // style necessarily = "vintage"
{
private:
char * nickname; // i.e., "The Noble" or "Old Velvet", etc.
int year; // vintage year
public:
VintagePort();
VintagePort(const char * br, const char *st, int b, const char * nn, int y);
VintagePort(const VintagePort & vp);
~VintagePort() { delete[]nickname;}
VintagePort & operator=(const VintagePort & vp);
virtual void Show() const;
friend ostream & operator<<(ostream & os, const VintagePort & vp);
};
I have to explain why operator=() and operator<<() are not
virtual. I think that operator<<() can't be virtual because only class methods could be, but I have no idea about operator=(). How does the pointer at basic class know which one of operator=() it has to use?
Second question is about how I can make operator<<() behave like a virtual method for example:
basicClass B;
inheritClass I;
basicClass *ptr;
ptr=&I;
std::cout << ptr // Here I'd like to use operator<<(std::ostream, inheritClass)
operator = is not virtual because it is not marked virtual. The declaration of operator = looks like this
//No virtual here
Port& operator =(const Port&);
If, however, operator = was virtual it would be declared like this
virtual Port& operator =(const Port&);
^^^^^^^ Virtual here!
Since operator = is not virtual the compiler uses static linkage when compiling. This means the function called is dependent on the type of the variable it is being referred to by. Consider this code:
VintagePort vp;
//Calls VintagePort::operator =(const VintagePort&)
vp = VintagePort();
Port* p = &vp;
//Calls Port::operator =(const Port&)
*p = Port();
VintagePort::operator = is called when it is being accessed as a VintagePort, however, Port::operator = is called when it is accessed as a Port. (Live example here.)
To make operator << behave as if it were virtual you would have to declare a virtual member function within your class that does the printing. Something like this
//Inside Port
virtual void Print(std::ostream& os) const
{
os << brand << ' ' << style << ' ' << bottles;
}
Then in every class that derives from Port (like VintagePort) you would override the method to also print the values for that derived class. So for VintagePort you could do this
//Inside VintagePort
void Print(std::ostream& os) const
{
//Make Port print first
Port::Print(os);
os << ' ' << nickname << ' ' << year;
}
Then in operator << all you would have to do is to call the Print method on the argument. Which would look like this:
std::ostream& operator <<(std::ostream& os, const Port& p)
{
P.Print();
return os;
}
As a plus you don't have to overload operator << for every derived the class as the overload only needs the virtual function in the Port class.
This has the feeling of a codereview which is not what SO is for -- but anyways:
Don't use character arrays. Use std::string:
class Port
{
private:
std::string brand;
std::string style; // i.e., tawny, ruby, vintage
//...
};
Moreover, and in general, don't use pointers where objects are appropriate. And if you need pointers, use smart pointers to clearly express the purpose.
This is the RAII principle which underpins most of C++.
If you follow the previous suggestion, there is no need to define: destructors, copy/move constructors, and -- that touches your question -- also not assignment operators. (And particularly, there is no need to overload the latter).
operator<< can't should not declared virtual, as it is not a class member. It's a stand-alone function which, due to being a friend, may have access to private members of your port wine classes.
But you can overload it outside of the class. This is what one straightforwardly does by setting up different overloads as operator<<(ostream & os, const Port & p); and operator<<(ostream & os, const VintagePort & p);.
Related
I have a problem with polymorphism and inheritance.
The parent class is:
class IIR_filter {
private:
double* a_;
double* b_;
unsigned int order_;
void reverseArray(double* source, double* destination, unsigned int size);
public:
IIR_filter();
IIR_filter(double* a, double* b, unsigned int order); //c'tor
IIR_filter(const IIR_filter& filter); //copy c'tor
virtual ~IIR_filter(); //d'tor
virtual void filter(double* inputX, double* outputY, unsigned int size);
virtual void zeroPhaseFilter(double* inputX, double* outputY, unsigned int size);
friend ostream& operator<<(ostream& lhs, const IIR_filter& rhs);
protected:
double filterSample(unsigned int indexY, double* outputY,double newSample, Queue<double>& filter);
double getElementA(unsigned int index) const;
double getElementB(unsigned int index) const;
unsigned int getOrder() const;
virtual void print(ostream& lhs, const IIR_filter* rhs)const;
};
and the cpp relevant functions are:
ostream& operator<<(ostream& lhs, const IIR_filter& rhs){
std::cout << "IIR filter: " << std::endl;
rhs.print(lhs, &rhs);
return lhs;
}
and the derived class is:
class FIR_filter : public IIR_filter {
public:
FIR_filter(double* b, unsigned int order); //c'tor
friend ostream& operator<<(ostream& lhs, FIR_filter* rhs);
};
And the cpp function is:
ostream& operator<<(ostream& lhs, FIR_filter* rhs){
lhs << "FIR filter: \n";
rhs->print(lhs, rhs);
return lhs;
}
And of course there is the print function in the IIR_filter class, but it's too long and irrelevant for my opinion.
The problem is:
When I call the printing function (operator<<) from an object of the derived class, the print is done from the parent class, so instead of the header "FIR filter" i get the header "IIR filter".
I have tried many ways but have no success.
Please help.
Thank, Ran.
You should move the writing of a header into a stream inside the virtual print function, and create a suitable override in the derived class. You might also want to refactor the code to have a virtual print_header function called inside a non-virtual print, since you're currently not overriding it in the derived class.
By the way, you have inconsistency - one operator<< is accepting a reference to a const object, and the other is accepting a pointer. But even if you unified your convention, the operator<< is still not virtual, so it cannot determine in runtime if the reference (or pointer) to the base type indeed points to a derived object. It means, that in current state, it will (and should) always print the "IIR filter" header.
You can't derive friend ship.
See this question for more details:
friend class with inheritance
Also, like that was mentioned before, You should have one overloaded operator<< in base class which just returns only output of print function. Than in print implementations You can do all printing and other stuff for all Your classes.
I was wondering if there is any way to overload the << operator for a class without declaring it as a friend function. My professor said this is the only way to do it, but I wanted to know if there is another way that he was unaware of.
There is no need to make the operator<< function a friend of the class as long as everything you want to be output is accessible through the public interface of the class.
You need to declare it is as friend function if and only if you need access to it's private members.
You can always do this without using friend function if:
1) No private member access is required.
2) You provide a mechanism to access your private member otherwise. e.g.
class foo
{
int myValue;
public:
int getValue()
{
return myValue;
}
}
Yes, you can
std::ostream& operator<<(std::ostream &stream, WHATEVER_TYPE var) {
std::string str = somehowstringify(var);
return stream << str;
}
Note however that by virtue of it being a non-member non-friend function it can of course only access the public interface of std::ostream, this usually isn't a problem.
Yes, one way to do it is like this:
class Node
{
public:
// other parts of the class here
std::ostream& put(std::ostream& out) const { return out << n; };
private:
int n;
};
std::ostream& operator<<(std::ostream& out, const Node& node) {
return node.put(out);
}
As R Sahu has pointed out, the requirement is that the operator should be able to access everything it has to display.
Here are a few possible options
1.Adding the overloaded function as a friend function
2.Making all the required data members of the class accessible for the function using either public accessor methods or public data members
class MyClass {
private:
int a;
int b;
int c;
public:
MyClass(int x,int y,int z):a(x),b(y),c(z) {};
MyClass():a(0),b(0),c(0) {};
int geta() { return a; }
int getb() { return b; }
int getc() { return c; }
};
std::ostream& operator<<(std::ostream &ostr,MyClass &myclass) {
ostr << myclass.geta()<<" - " << myclass.getb() << " - " << myclass.getc() ;
return ostr;
}
int main (int argc, char const* argv[])
{
MyClass A(4,5,6);
cout << A <<endl;
return 0;
}
3.Add a public helper function , say output with the signature std::ostream& output(std::ostream& str) and use it later in the operator function.
I have a slight problem where my << operator is not being called correctly.
This is what I have:
class SomeInterface
{
friend std::ostream& operator<<(std::ostream& str, const SomeInterface& data);
protected:
virtual void print(ostream& str) const = 0;
};
inline std::ostream& operator<< (std::ostream& o, SomeInterface const& b)
{
b.print(o);
return o;
}
}
Calling code looks something like:
SomeInterface* one = new someConcrete ();
cout << one;
The << overloaded function I was hoping would get called on the interface is not, let alone dispatching through to the derived class.
Try:
cout << *one;
Your code is asking to print the pointer, while your operator<< takes a const SomeInterface& reference.
You are calling std::ostream& operator<< (std::ostream& o, void*);, because the type of one is a pointer.
Try:
cout << *one;
This will call the overload that takes a (reference to) the actual object, not the pointer itself
Anyone got an idea on how to write an operator for a class that isn't a member function of the class?
Just make it a free function, or a friend function. A good example of this is operator<<:
class X {
public:
int x;
}
ostream& operator<< (ostream& os, const X& x) {
os << x.x;
return os;
}
The benefit of making it a friend function is that you have direct access to private members, whereas a free function must access all members via public methods.
Arithmetic operators, stream operators, et cetera are often not members of a class. However, they may need to be friends in order to access private data members.
I prefer not to use friend and to expose methods that can be used by the operators instead. I believe this to be more in keeping with the Open/closed principle, as I could easily add a subtraction operator without editing the class.
These are handy for unit-testing, too (I can "inject" a std::ostringstream to test the output of print(), for instance).
Here is an example:
#include <iostream>
class Number
{
public:
Number(int j)
:i(j)
{
}
void print(std::ostream& os) const
{
os << i;
}
int value() const
{
return i;
}
private:
int i;
};
std::ostream& operator <<(std::ostream& os, const Number& n)
{
n.print(os);
return os;
}
Number operator +(const Number& n, const Number& o)
{
return Number(n.value() + o.value());
}
int main()
{
Number a(4), b(5), c(a + b);
std::cerr << c << std::endl;
}
Just declare the global function with the operator name:
Point operator+(Point& p, Vector& v) {
return new Point(p.x + q.i, p.y + q.j);
}
Basically, you can take the operator out of the class, and add a parameter to the beginning of the parameter list. In many cases, you will also need to declare the operator function as a friend.
For instance
class Foo
{
Foo operator +( Foo const& other );
};
becomes
class Foo
{
friend Foo operator +( Foo const&, Foo const& );
};
Foo operator +( Foo const& first, Foo const& second );
The friend statement allows the operator to still access any private or protected members needed.
Note that there are some restrictions on which operators can be overloaded in this manner. See this article for such a list.
In a project I'm working on, I have a Score class, defined below in score.h. I am trying to overload it so, when a << operation is performed on it, _points + " " + _name is printed.
Here's what I tried to do:
ostream & Score::operator<< (ostream & os, Score right)
{
os << right.getPoints() << " " << right.scoreGetName();
return os;
}
Here are the errors returned:
score.h(30) : error C2804: binary 'operator <<' has too many parameters
(This error appears 4 times, actually)
I managed to get it working by declaring the overload as a friend function:
friend ostream & operator<< (ostream & os, Score right);
And removing the Score:: from the function declaration in score.cpp (effectively not declaring it as a member).
Why does this work, yet the former piece of code doesn't?
Thanks for your time!
EDIT
I deleted all mentions to the overload on the header file... yet I get the following (and only) error. binary '<<' : no operator found which takes a right-hand operand of type 'Score' (or there is no acceptable conversion)
How come my test, in main(), can't find the appropriate overload? (it's not the includes, I checked)
Below is the full score.h
#ifndef SCORE_H_
#define SCORE_H_
#include <string>
#include <iostream>
#include <iostream>
using std::string;
using std::ostream;
class Score
{
public:
Score(string name);
Score();
virtual ~Score();
void addPoints(int n);
string scoreGetName() const;
int getPoints() const;
void scoreSetName(string name);
bool operator>(const Score right) const;
private:
string _name;
int _points;
};
#endif
Note: You might want to look at the operator overloading FAQ.
Binary operators can either be members of their left-hand argument's class or free functions. (Some operators, like assignment, must be members.) Since the stream operators' left-hand argument is a stream, stream operators either have to be members of the stream class or free functions. The canonical way to implement operator<< for any type is this:
std::ostream& operator<<(std::ostream& os, const T& obj)
{
// stream obj's data into os
return os;
}
Note that it is not a member function. Also note that it takes the object to stream per const reference. That's because you don't want to copy the object in order to stream it and you don't want the streaming to alter it either.
Sometimes you want to stream objects whose internals are not accessible through their class' public interface, so the operator can't get at them. Then you have two choices: Either put a public member into the class which does the streaming
class T {
public:
void stream_to(std::ostream&) const {os << obj.data_;}
private:
int data_;
};
and call that from the operator:
inline std::ostream& operator<<(std::ostream& os, const T& obj)
{
obj.stream_to(os);
return os;
}
or make the operator a friend
class T {
public:
friend std::ostream& operator<<(std::ostream&, const T&);
private:
int data_;
};
so that it can access the class' private parts:
inline std::ostream& operator<<(std::ostream& os, const T& obj)
{
os << obj.data_;
return os;
}
Let's say you wanted to write an operator overload for + so you could add two Score objects to each other, and another so you could add an int to a Score, and a third so you could add a Score to an int. The ones where a Score is the first parameter can be member functions of Score. But the one where an int is the first parameter can't become member functions of int, right? To help you with that, you're allowed to write them as free functions. That is what is happening with this << operator, you can't add a member function to ostream so you write a free function. That's what it means when you take away the Score:: part.
Now why does it have to be a friend? It doesn't. You're only calling public methods (getPoints and scoreGetName). You see lots of friend operators because they like to talk directly to the private variables. It's ok by me to do that, because they are written and maintained by the person maintaing the class. Just don't get the friend part muddled up with the member-function-vs-free-function part.
You're getting compilation errors when operator<< is a member function in the example because you're creating an operator<< that takes a Score as the first parameter (the object the method's being called on), and then giving it an extra parameter at the end.
When you're calling a binary operator that's declared as a member function, the left side of the expression is the object the method's being called on. e.g. a + b might works like this:
A a;
B b
a.operator+(b)
It's typically preferable to use non-member binary operators (and in some cases -- e.g. operator<<for ostream is the only way to do it. In that case, a + b might work like this:
A a;
B b
operator+(a, b);
Here's a full example showing both ways of doing it; main() will output '55' three times:
#include <iostream>
struct B
{
B(int b) : value(b) {}
int value;
};
struct A
{
A(int a) : value(a) {}
int value;
int operator+(const B& b)
{
return this->value + b.value;
}
};
int operator+(const A& a, const B& b)
{
return a.value + b.value;
}
int main(int argc, char** argv)
{
A a(22);
B b(33);
std::cout << a + b << std::endl;
std::cout << operator+(a, b) << std::endl;
std::cout << a.operator+(b) << std::endl;
return 0;
}