Properly declaring a function using class members? - c++

I'm in the process of trying to convert a C program using structs into C++ with classes. I am trying to call a member function of a class B from within class A. Here is a snippet to explain my error:
class Time{
public:
Time();
Time(int hour, int minute);
int time_Equal(Time &a, Time &b) const;
-----
private:
int hour;
int minute;
};
Boolean Time::time_Equal(Time &a, Time &b) const
{
/* If hour of Time "a" equals hour of Time "b" */
if(a.hour == b.hour){
if(a.minute == b.minute)
return TRUE;
}
}
class DaTime{
public:
DaTime();
DaTime(Day day, Time start, Time end);
Boolean dt_Equal(DaTime &a, DaTime &b) const;
private:
int duration;
Time start;
Time end;
};
Boolean DaTime::dt_Equal(DaTime &a, DaTime &b) const
{
if(time_Equal(a.start, b.start)){
if(time_Equal(b.end, a.end))
return TRUE;
}
else
return FALSE;
}
The error I am getting is that time_Equal is not declared in this scope. The reason I do not understand this is because I have included a header file where Time is declared before DaTime. I don't see the issue with how I have declared the functions.

First, note that the boolean type is just bool.
Second, the return type of the time_Equal declaration is int, whereas the definition has Boolean. Pretty sure you want both to be bool. They should at least match.
Third, your time_Equal function does not modify its arguments, so you should make them const references (const Time &a and const Time &b).
Fourth, your time_Equal function is a non-static member of Time, but it doesn't use any of its members. That is, its output depends only on its arguments, and not on the object that this points at. This is a code smell. It means your function should probably be a static function or you should change the function to use this. So you have two options:
Keep it a member and change it to:
bool time_Equal(const Time &other) const;
And then in the implementation you should compare *this with the other argument. In this case, you would call it like a.start.time_Equal(b.start).
Make it either a static member or take it out of the class and make it a friend function and keep it with two arguments:
bool time_Equal(const Time &a, const Time &b) const;
In this case, you would call it like time_Equal(a.start, b.start).
Fifth, C++ has a built in operator to perform test for equality (==) which you can overload for a class. So you can in fact implement the above two options respectively like so:
bool operator==(const Time &other) const; // As a non-static member
// or
bool operator==(const Time &a, const Time &b) const; // As a static member or friend function
Then you can compare times like so: a.start == b.start. Nice, huh?
For more information, see the operator overloading FAQ.
Sixth, your time_Equal implementation does not return false when it should. You can easily rewrite the body as:
return a.hour == b.hour && a.minute == b.minute;

Function time_Equal is declared as a non-static member function of a class. So it can be used only with an instance of the class.
Moreover it is declared as having parameters of type Time. However in function dt_Equal you call it passing arguments of type int
if(time_Equal(a.start, b.start)){
if(time_Equal(b.end, a.end))
return TRUE;
}
You should declare function time_Equal either as a non-member function with two parameters or as member function with one parameter.
As a member function it could look as
bool Time::time_Equal( const Time &rhs ) const
{
return ( hour == rhs.hour && minute == rhs.minute );
}
As a non-member function it must be declared as a friend function of the class because data members hour and minute are defined as private Or if you have getters to hour and minute then there is no necessary to make it friend. In any case it could look as
bool Time::time_Equal( const Time &lhs, const Time &rhs )
{
return ( lhs.hour == rhs.hour && lhs.minute == rhs.minute );
// or return ( lhs.get_hour() == rhs.get_hour() && lhs.get_minute() == rhs.get_minute() );
}

time_Equal is a method in the Time class, yet you call it like it is a global function.
An instance level method shall be called on an object.

Related

Overloading the == operator

I am trying to compare member variables of 2 objects from the same class
in Donor.h
friend bool operator==(const Donor& donor1,const Donor& donor2);
And in Donor.cpp
bool Donor::operator==(const Donor& donor1, const Donor& donor2)
{
if (donor1.get_type() == donor2.get_type())
{
return true;
}
else
return false;
}
but i get an comple error
bool Donor::operator==(const Donor& donor1, const Donor& donor2) must have exactly one argument.
What am I doing wrong?
A friend function is not a member function. It cannot be defined as Donor::operator==, it must be just operator==.
The error message is less than helpful here. It is saying that a operator== member function only takes a single argument, but since you do not want to make it a member function, that is information you do not need.

Overloading the comparison operator for object members

Say I have a class called book:
class Book {
int i;
public:
Book(int ii)
: i(ii) {
}
int ISBN() {
return i;
}
};
I want to overload the comparison operator for the Book class, so that I can create a bool function that will compare the member "i" when it comes across book1==book2.
bool is_same() {
return (book1==book2) ? true : false;
}
How would I go about this? This is the current operator overload function I have, it gives me an "invalid initialization of non-const reference of type 'Book&' from an rvalue of the type 'bool'" error. I currently have my overloaded function inside of the class Book as a public function.
Book& operator==(const Book& b) const {
return ISBN() == b.ISBN();
}
I'm relatively new to operator overloading, I have sifted through many answers but none of them resolve my issue. I understand how one could simply do book1==book2, but that would only return true if every single member was of the same value. In this case I have more than just one, but I only want to return true if "i" is the same for both objects.
You basically have 2 choices:
use a member operator with one argument:
class Book {
...
bool operator==( const Book &an ) const { return ISDN() == an.ISDN(); }
};
use a non-member operator (and possibly a friend statement) with 2 arguments:
bool operator==( const Book &b1, const Book &b2 )
{
return b1.ISBN() == b2.ISBN();
}
Note that ISDN() should be made const.
Either way, you need to return a bool, not a Book &, which is usually returned by the assignment operator =, not the comparison operator ==.

Comparing two objects of the same class

I am trying to overload the == operator in C++.
#include <string>
using namespace std;
namespace date_independent
{
class clock
{
public:
int clockPair[2] = {0,0};
operator string() const
{
string hourString;
string minString;
if(clockPair[0]<10)
{
hourString = "0"+to_string(clockPair[0]);
}
else
{
hourString = to_string(clockPair[0]);
}
if(clockPair[1]<10)
{
minString = "0"+to_string(clockPair[1]);
}
else
{
minString = to_string(clockPair[1]);
}
return hourString+":"+minString;
};
bool operator ==(const clock&clockOne, const clock&clockTwo) const
{
return string(clockOne)==string(clockTwo);
};
};
};
There is much more code than I have included, but this is the important part. I want it so that the == operator can compare two objects of class clock. E.g., object1==object2. Is there anybody that can help me?
A binary operator like == can be overloaded either as a member function with a single parameter (this being the left-hand operand, and the parameter being the right-hand one), or as a non-member function with two parameters for the two operands.
So either
move your operator declaration outside the class declaration (moving the definition to a source file, or declaring it inline if you keep the definition in the header); or
add friend to the definition, so that it declares a non-member in the surrounding namespace; or
remove the first argument from the member function, using this instead.
As a member, it would look like
bool operator==(const const & clockTwo) const {
return string(*this) == string(clockTwo);
}
You might also want to compare the two integer values directly to save the expense of making strings. You should also remove the rogue ; after the function and namespace definitions, although most modern compilers shouldn't object to their presence.
Your comparison function has been written to take two clock objects and compare them, so it should be a non-member function (after the class definition), without the const qualifier.
bool operator==(const clock& clockOne, const clock& clockTwo)
{
return string(clockOne) == string(clockTwo);
}
When you have an operator inside the class definition, the left-hand argument is implicitly provided for you (it's *this), so if you wanted to implement it there you'd need something like:
bool operator==(const clock& clockTwo) const
{
return string(*this) == string(clockTwo);
}
Still, that's not recommended for == as if you have say an implicit constructor from another type T, you won't be able to write code ala my_t == my_clock with the member version unless T provides a suitable comparison operator (for clock or string). A non-member operator gives more symmetric operation.
Overloading can be done inside or outside the class definition. If you want to do it inside, the function receives only one argument. You should compare this with that argument.
bool operator ==(const clock&clockTwo) const
{
return string(*this)==string(clockTwo);
}
Note the const after the argument, it means that you won't change this inside the function.
On the other hand, if you want to do it outside the class definition, it needs two arguments, and you should compare them.
bool operator ==(const clock&clockOne, const clock&clockTwo)
{
return string(clockOne)==string(clockTwo);
}
Also note that it'll be faster to compare the clockPair of the objects rather than making the string and comparing them.
Though your question is poorly worded I believe that you are asking why the operator you've defined is not working?
If you are defining the operator as a member of the class it only takes one parameter. For example:
class clock {
bool operator ==(const clock& rhsClock) const
{
// Note: this is the lhsClock
return string(*this) == string(otherClock);
}
};
When you define the operator as a free function (not as a part of the class) then you need to define both parameters:
class clock {
// ... class declaration ...
};
bool operator ==(const clock& lhsClock, const clock& rhsClock)
{
return string(lhsClock) == string(rhsClock)
}
Where the comparison would look like this:
if (lhsClock == rhsClock) // ... do something ...

`bool operator<(Contact&)' must take exactly two arguments

I have
class Conatact{
.....
bool operator<(Contact &c);
};
bool operator<(Contact &c)
{
return this.getName<c.getName();
}
it says `bool operator<(Contact&)' must take exactly two arguments
when I try to change it to have two arguments
bool operator<(Contact &c)
{
return this.getName<c.getName();
}
it says it must take exactly one argument
I think you need to indicate to the compiler it's a member implementation by supplying a fully qualified name:
bool Conatact::operator<(Contact &c)
{
return this->getName() < c.getName();
}
It would be a good idea to make your operator const, and to make the Contact &c const as well.
Without the scope resolution qualifier, the compiler thinks that you are defining a "free-standing" operator to compare contacts, in which case the operator would indeed need to take two arguments:
bool operator<(const Contact &lhs, const Contact &rhs) {
...
}

template class and overloading '=='

I'm making some stack, in which I need to uses this kind of comparison in some function. But I got stuck since I don't know how the prototype for this should look like.
I have the following line in a function.
template <class T>
void function1(T i)
{
if(i == 'a')
//do something
}
I wonder know how the overload prototype should look like for it?
EDIT
Dunno if it's worth to mention, anyway this is what I have tried so far
template
bool Stack<T>::operator==(char c) const
{
cout << c << endl; // just some test
}
No need to comment how this function works, as I have not finished it yet. This part will compile, however at the part where I call this function for the first time is in the Stack::push(T i). The compiler will complain that there are no matching function for this.
error: no match for 'operator==' in 'i == '#''
For overloading operators, the name of the function is operator followed by the actual operator, so operator==. It returns bool. I don't know what your arguments should be based on your code. Probably Stack<T>&, and you need two of them to compare if it's a free function, and one to compare to this if it's a member function.
If you have ways to convert to a Stack<T>, then prefer a free function so that you can convert the left-hand-side.
I'm not sure I understand your question. In order for an instantiation of template function function1 to be well-formed, you'll have to provide a operator== which compares a T and (I'll suppose) a char.
Now, you have two options here :
Provide a bool operator==(char) const member function in your type, for example :
struct A {
bool operator==(char) const { /* ... */ }
};
function1(A()); // OK : comparison uses A::operator==(char)
Provide bool operator==(const T &, char) as a free function, for example :
struct A { /* ... */ };
bool operator==(const A &, char) { /* ... */ }
function1(A()); // OK : comparison uses operator==(const A &, char)
So every T in your function1(t) has to implement operator ==;
For example, as a member function
class A
{
public:
bool operator == (char) const;
};
or a non-member operator:
class A
{
public:
friend bool operator == (const A&, char);
};