When to use const before function and when you shouldn't - c++

I can't figure this out. I'm trying to recreate "complex" c++ class and those functions.
For example: real(), imag(), abs() etc. use parameters as const complex& obj. So I thought if you pass object by its reference it is not copied and saves a bit of memory and is faster and use const in front of it to avoid messing up that object. Am I right?
So I thought I could create my functions like those as well, but why those functions that have parameter with const need to be const functions them selves?
Here is what I got:
class MyComplex{
private:
double real;
double imag;
public:
MyComplex();
MyComplex(int real);
MyComplex(int real, int imag);
double getReal();
double getImag();
void setReal(int real);
void setImag(int imag);
friend const double real(const MyComplex& obj);
friend const double imag(const MyComplex& obj);
friend const double abs(const MyComplex& obj);
friend const double arg(const MyComplex& obj);
friend const double norm(const MyComplex& obj);
friend const std::string conj(const MyComplex& obj);
friend std::string myPolar(double rho, double theta);
};
If I don't put const in front of them they don't work.
const double real(const MyComplex& obj){
return obj.real;
}
Other functions are very similar.

Your design is bad.
What you should change:
getReal and getImag should be const-member-functions (Add the qualifier after the parameter-list).
All those friend-functions should not be so friendly, implement them just with the public interface.
(Remember that encapsulation means minimizing the amount of code depending on the classes internal details.)
Anyway, there is seldom a reason to have a const-qualified return-type. I never had one.
Making the return-type const might even sometimes break things.

The declaration
friend const double real(const MyComplex& obj);
does not declare a const function, it declares a non-const function that returns a constant value. Since you return by value anyway, this const is plain useless.
A const function is declared like this:
//within the class definition
double getReal() const;
This makes the implicit parameter to getReal(), the this pointer, const, allowing you to do myConstComplex.getReal().
And, as Deduplicator correctly notes, just kick those friends, you don't need them and you don't want them.

There's no reason to return const built-in type or object.

Related

using friend function with const reference in operator overloading

The code below cannot be compiled. However, when I remove "const" from Point& of the friend function, this code turns to be compiled. Could anyone explain the reason why?
class Point
{
public:
Point(double x, double y);
Point operator+(const double& add);
friend Point operator+(const double& add, const Point& p){return p+add;}
private:
double px, py;
};
Point::Point(double x, double y): px(x), py(y){}
Point Point::operator+(const double& add){
return(Point(px+add, py+add));
}
int main(){}
The operator+ is not marked as a const, yet is tried to be called through a const reference.
Constant pointers and references are only allowed to call member functions that are marked constant (since the compiler definitely knows that those functions are ensured not to modify internal state).

printing with polymorphism and inheritance

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.

operator overloading and non-member functions c++

I have written a class for complex numbers in which I have overloaded the operator + and everything works fine, however I need to implement this as a non-member function and I am not sure how, or why there is a benefit of doing so.
Here is my code .h:
class Complex
{
private:
double a;
double b;
public:
Complex();
Complex(double aGiven);
Complex(double aGiven, double bGiven);
double aGetValue();
double bGetValue();
double operator[](bool getB);
Complex add(Complex &secondRational);
Complex operator+(Complex &secondRational);
}
.cpp:
Complex Complex::add(Complex &secondRational)
{
double c = secondRational.aGetValue();
double d = secondRational.bGetValue();
double anew = a+c;
double bnew = b+d;
return Complex(anew,bnew);
}
Complex Complex::operator+(Complex &secondRational)
{
return add(secondRational);
}
Any help on how to make these as non-member functions will be greatly appreciated!
Here is the addition operator outside of the class:
Complex operator+(const Complex& lhs, const Complex& rhs) {
//implement the math to add the two
return Complex(lhs.aGetValue() + rhs.aGetValue(),
lhs.bGetValue() + rhs.bGetValue());
}
Of course you will need to declare aGetValue() and bGetValue() as const:
double aGetValue() const {return a;}
double bGetValue() const {return b;}
The usual approach to arithmetic operations is to define the reflexive versions of the operators as members and the pure versions as non-members, implementing them with the reflexive versions:
class complex {
public:
const complex& operator+=(const complex& rhs) {
real += rhs.real;
imag += rhs.imag;
return *this;
}
};
complex operator+(const complex& lhs, const complex& rhs) {
complex res(lhs);
res += rhs;
return res;
}
How is explained above by pippin1289.
Why is explained below:
Imagine one need to use object of class as
Complex c3 = 5 + c1;// for c3 object c1's real part (a) added with 5
As C++ preserve order of operand. Compiler resolve above addition call as
5.operator+ (const Complex & other);// which is not possible
Hence, overload it via free function.
Your class is exposing necessary information via public interface such as aGetValue() and bGetValue.
Hence, this free overloaded + operator function need not be friend of class.
Additionally, Prefer non friend non member function over member function as it helps reduce degree of encapsulation.
This is explained here ==> http://www.drdobbs.com/cpp/how-non-member-functions-improve-encapsu/184401197?pgno=1
You can declare a friend to your Complex class
class Complex {
// blah....
friend Complex operator+(Complex const& a, Complex const & b);
};
The overloaded operator can access the private members of Complex.

Creating a set of classes

I'm trying to create a set that can be filled with instances of a class. I thought that a requirement for a set is that elements can be compared, and thus in this case I need to tell my class how they can be compared. I created the following class:
class Myclass
{
public:
Myclass(int i):storedval(i) {}
int getval(){return storedval;}
friend bool operator> (Myclass &first, Myclass &second)
{
return first.getval()>second.getval();
}
friend bool operator< (Myclass &first, Myclass &second)
{
return first.getval()<second.getval();
}
private:
int storedval;
};
But when I try to add instances to a set like this:
Myclass a(50);
set<Myclass> Bunchofclasses;
Bunchofclasses.insert(a);
It gives me a bunch of error text that I think tells me it doesn't understand the > and < operators. How should this be done properly?
You need to pass const references to the comparison function because it should not be allowed to modify the items being compared:
friend bool operator< (const Myclass& first, const Myclass& second)
{ // ^^^^^ ^^^^^
return first.getval() < second.getval();
}
This will require that you make getVal() const as well. This makes it callable on const instances or via const references:
int getval() const {return storedval;}
// ^^^^^
Note that you do not need operator> for the set to work. Less-than is enough.
Strictly speaking, you do not need a friend function here, since you are calling public member functions. The only thing that friend brings here is to allow you to declare a non-member function inside of the class definition.
Elements of a set are immutable, so the set needs to be able to compare const values. So the comparison needs to be:
friend bool operator< (Myclass const &first, Myclass const &second)
// ^^^^^ ^^^^^
(You should probably also do this with operator> and any other non-mutating operations you provide; but set only needs operator<).
Also, in order to access the value of a const object, the accessor also needs to be const:
int getval() const
// ^^^^^

C++ operator overriding w/ arguments from 2 classes

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);