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.
Related
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);.
I have following class.
class Student {
//Parameterized constructor.
private:
int rollNo;
char* name;
float marks;
}
I have a set<Student> students. When I insert a student object in set, how can I sepcify that two objects are same. E.g. I am considering two objects same if their rollNo is same so Student s1(10,"ABC",35) and Student s2(10,"XYZ",67) both are same. So when I say students.insert(s1) and students.insert(s2), set will have only one object i.e. s1.
I've never done this in c++ but a quick look at http://www.cplusplus.com/reference/set/set/set/
explains it nicely.
Basically when you instantiate the set you need to give it a comparison object which " returns true if the first argument goes before the second argument"
for ints it could be
struct classcomp {
bool operator() (const int& lhs, const int& rhs) const
{return lhs<rhs;}
};
in your case that would be more like
struct StudentCompare{
bool operator() (const Student& lsh, const Student& rhs) const
{
return lhs.rollNo < rhs.rollNo; //or however they need to be compared
}
};
and then you can instantiate it like
std::set<int,StudentCompare> mySet;
This wont work as is for your code as rollNo is private. I recommend that you read the page i linked to above to better understand is going on.
You need to declare and define friend operator> for class Student
Example code
class Student {
/* everything you already have */
public:
friend bool operator<(const Student& lhs, const Student& rhs);
};
bool operator<(const Student& lhs, const Student& rhs) {
return lhs.rollNo < rhs.rollNo;
}
Solution provided thermite does not work because compare function doesn't have access to private members of class Student. To solve this problem, you can declare operator< as friend. A friend function (or class) can access the private and protected members of the class in which it is declared as a friend.
The way I do this is just define the less then operator - if neither of two elements is less then the other then they are effectively equal/equivalent to each other - the "original" thread linked by Daniel shows this nicely.
I'm new to object oriented programming and I'm wondering if it's possibile to create an operator for one class which will use arguments from this class and another one, declared by me.
The problem I have to solve is a linear translation on a given point. So I created classes Point and LinearTranslation and basically what I want to do is to create an operator
Point operator* (Point p, LinearTranslation l)
which would take Point p, do the translation l and then return Point. I'm getting weird errors though: Point operator*(int)’ must have an argument of class or enumerated type or that LinearTranslation has not been declared.
Is it even possibile?
ok i'm posting only a bit because it's kind of assignment so I have class Point.h
sorry for the mess but I'm trying a bit everything and it's not working for me.
#include "LinearTranslation.h"
class Point {
public:
int N;
double* coordinates;
public:
Point(int, double*);
virtual ~Point();
double operator[](int a);
//friend Point operator*(LinearTranslation l);
friend Point translation(LinearTranslation l);
};
LinearTranslation.h
#include "Point.h"
class LinearTranslation {
private:
int N;
double* vector;
double** matrix;
public:
//friend class Point;
LTrans(int,double*,double**);
LTrans(int);
virtual ~LTrans();
void write_vector();
void write_matrix();
LinearTranslation operator+(const LinearTranslation&);
friend Point& translation(LTrans l, Point p);
//friend Point& operator* (Point p, LTrans l);
};
in your class declaration:
//friend Point operator*(LinearTranslation l);
a friend operator overloading function takes two parameters for the function, you only declare one in your code. The most common example of a friend function is using the overloaded operator << like so:
friend ostream& operator<<(ostream& output, const Point& p);
note that this function takes the output as its first parameter, and the point as its second parameter.
Your fix would be to add in your operand to the function
friend Point operator*(LinearTranslation l, const int& MULT);
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;
}