C++ Class Inheritance and assignment operator - c++

I came here to ask something I can't figure out on my own. I've been coding a little class that stores an array of 32 bits and can perform simple mathematic operations like +, -, / and *.
Suppose I have a class like:
class Binary_Class
{
char bin[32]; // 32 bits array to hold an unsigned binary number
void set_dec(int value){}; // setting the bin[32] value based on input value
// I have operator + and = to perform on objects of this class.
Binary_Class& operator= (const Binary_Class&);
const Binary_Class operator+ (const Binary_Class&);
}
Until now, no problem comes up if i declare 3 objects a,b,c of class Binary_Class, then set_dec to a and b, the statement c=a+b can be used (?)
However, I want to extend the class binary by using a new class
class Binary_Class_Extended: public Binary_Class
{
// weird functions
}
If I declare 3 objects a, b, c of class Binary_Class_Extended, am I still able to use c=a+b as the same before that?
In Netbean it says there's no operator= that match my c=a+b if all are of Binary_Class_Extended,
but if I declare c as Binary_Class that statement works. That means a+b returns a const Binary_Class as if the operator+ doesn't get carried to the new class.
Am I missing something or this is the way it is?
Of course, I can post the whole code because it's just an assignment but I think these infos are enough for now.
Update
class Binary_Class
{
char bin[32]; // 32 bits array to hold an unsigned binary number
void set_dec(int value){}; // setting the bin[32] value based on input value
//i have operator + and = to perform on objects of this class.
Binary_Class& operator= (const Binary_Class&);
const Binary_Class operator+ (const Binary_Class&) const;
}
class Binary_Class_Extended: public Binary_Class
{
// weird functions
}
When I try to have all objects of Binary_Class_Extended this error show up:
main.cpp:285: error: no match for 'operator=' in 'sd = ((Binary_Class*)(&sa))->Binary_Class::operator+(((const Binary_Class&)((const Binary_Class*)((Binary_Class*)(&sb)))))'
Binary_ET_Class sa,sb,sc;
sc=sa+sb //initialized sa and sb to non-null value;
The full source code I've been working on: https://pastebin.com/eiVz0f5p

Inherited functions retain their finger prints, so if the Binary_Class operator+ was inherited, it's return value would be ... ?

In general, inheritance and assignment ("value semantics") don't mix easily in C++. In your second case, the "a+b" would return an instance of the baseclass, unless you define a separator operator+ for the derived class. The result is then only assigned to the base-class part of "c", which is triggering the error. This is also sometimes call slicing/truncation. Note that the choice of the operator is at compile time, no virtual functions are called, so the static type has to match.
Don't mix value types and polymorphic types. If you really need to and you have a fixed and known hierarchy, you can use the "Handle-Body Idiom" to preserve derived information when assigning to the baseclass. This is not a beginner topic though.

Related

C++ bitset inheritance - How to fix type error with logical operators?

I am inheriting class from STL bitset.
Reasons:
I need same size bitsets in multiple places, so I want to define a type for them.
I want to add some extra methods in future, so I need a class.
Here's a sample code.
#include <bitset>
class MySet : public std::bitset<256> {
};
// This is not a real function, just PoC
MySet intersection(MySet &a, MySet &b) {
return a & b;
}
But on & operator I get error:
error: could not convert 'std::operator&<256>((& a)->MySet::<anonymous>, (& b)->MySet::<anonymous>)' from 'std::bitset<256>' to 'MySet'
What should I add to be able to use all logical operators defined in bitset for my class?
The result of a & b cannot be implicitely converted to MySet, since there is no suitable definition for such conversion. The workaround is to simply declare a constuctor. This:
public:
MySet(const std::bitset<256>& b)
: std::bitset<256>{b} { }
will be enough to make the code compile.

C++ User Defined Class Copy Assignment Missing?

I have written two custom classes, called A and B
My B class has a member variable a, and it has a function:
void B::setA(A s)
{
a = s;
}
However, this line is giving me an error:
'operator =' function is unavailable in 'A'.
From my understanding, this means somehow the compiler is not creating a default copy assignment function for my A class. However, I don't see why... the only constructor I've written in A looks like...
class A
{
//...
public:
A() {};
//...
};
Now in truth, A and B are large classes with a lot of member variables, and the names aren't really A and B. Short of posting the entire source for both of these classes, could anyone tell me what types of things I might look for when trying to diagnose that error message? Just to be clear, I never use pointers or low-level features like that so, as far as I know, the default copy-assignment should work fine for class A.
edit:
Someone mentioned that one of the member variables of A might be to blame, so here are all of the types:
const std::string
static const bool
static std::map<int,std::string>
std::vector
std::map<int, C>
where C is a struct that I defined in the same header file that A is in. It just contains a few integers and strings.
You have in class A a non-static data member declared as
const std::string
that is with the qualifier const. In this case the implicit copy assignment operator is defined by the compiler as deleted.
const members don't mix well with copy assignment operators. Not only won't the compiler generate one for you, it would also be semantically hard to come up with an "assignment" which does not actually assign everything.
Nothing stops you from writing an assignment operator which does not assign to your const member, of course, but that would mean one of two things:
The assigned object does not appear to the client as an identical copy of the source, which is not what one would except from a copy assignment operator, so that would be a case of operator-overloading abuse.
The member variable does not have an observable effect to the outside. In that case, one must wonder why it exists in the first place, or rather why it is not mutable rather than const.

How to overload an operator with multiple parameters like a + b + c?

I can operate class+class (for example I can do date+date), but can anyone explain how can I do class+class+class please? C++ does not let me define an operator with 2 parameters.
That's because there is no such operator in general.
a + b + c is (a + b) + c. First a + b, then the results
of that added to c.
EDIT:
If the objects in question are extremely big, so that creating
the temporaries in an expression like a + b + c is too
expensive, you can google for template expressions; the basic
idea is that operator+ doesn't do anything but return an
expression node, which can be evaluated later, as part of the
full expression.
By making them friends of the class, you would make sure they are binary operators, and define them separately, like so:
class someclass
{
int a;
public:
someclass();
...
friend someclass operator+(const someclass & lhs, const someclass & rhs);
};
someclass operator+(const someclass &lhs, const someclass &rhs)
{
someclass a = lhs;
a.a = a.a + rhs.a;
return a;
}
you will, of course need to define a copy constructor (someclass(const someclass & old);) and the other functions of the class, but this method has always worked for me, and it was how I was taught in college.
There are two ways you can approach this. The normal way with operators is, you just create a normal two operand operator, and then chain the calls together. For example a + b + c + d => operator+(operator+(operator+(a + b), c), d).
Alternately, create your own named function or member that provides a multi-parameter version, using the name to accurately describe what it does.
I suggest reading http://www.cs.rit.edu/~mjh/docs/c++-faq/operator-overloading.html
To the best of my understanding you do not need 2 parameters here. Your overload needs to return an object which the result of your operation. In this case your example class+class+class can actually be written as class+(class+class) so that (class+class) is processed first and then the result of that is added to the third class.
You are allowed to use arithmetic operators with two parameters. For example:
//References are used here as arguments.
Cents operator+(const Cents &c1, const Cents &c2)
{
// use the Cents constructor and operator+(int, int)
return Cents(c1.m_nCents + c2.m_nCents);
}
(Source: http://www.learncpp.com/cpp-tutorial/92-overloading-the-arithmetic-operators/)
Note: you need to declare the operator "function" as friend in class definition if you need to use private members of your class in it.
If you then return a class type same with those given as arguments (objects or references of them as here), you can do class + class + class..., assuming that each operator+ call is between 2 arguments, and the result is added to the third one invoking again the operator+ "function" etc.

inheritance and "invalid covariant return type" error on operator overloading

I have the following class representing numerical arrays
class Array {
protected :
double *data; // this will hold the data of the array
int n; // number of elements in the array
public :
virtual Array operator+ ( double value ) const {
// return a new array with the argument added to each element
}
// other declarations follow here...
};
and another class inheriting from the previous one and adding a boolean mask for each element
class MaskedArray : public Array {
private :
bool *mask; // this holds the boolean mask of the array
public :
MaskedArray operator+ ( double value ) const {
// return a new MaskedArray with the argument added to each element
}
// other declarations follow here...
}
When I try to compile I get the error "invalid covariant return type", which is normal since the two overloaded operators in both classes have the same signature.
I was able to circumvent this problem by passing the argument of the overloaded operator of the inherited class by reference rather than by value, as this changes the signature of the function, while keeping the same interface for both classes. But I feel this is not very clean, and what if I wanted to inherit from MaskedArray ? I would face the same problem.
I want to be able to write stuff like this in my client code
Array array;
// populate array here
Array array2 = array + 1.0;
MaskedArray maskedArray;
// populate maskedArray here
MaskedArray maskedArray2 = maskedArray + 1.0
Is there another more elegant way than my 'hack' to achieve this ?
Covariant means that the return type of an overridden virtual function is inherited from the return type of the base class function.
But: Although covariance is generally supported by C++, the standard allows covariance only when returning pointers or references. operator+ returns by value, that's why you get the compiler error. That is not specific to operators but applies to every function.
Removing the virtual keyword will eleminate the compiler error. But if you do so, keep in mind that applying operator+ to an Array reference or pointer, which actually references a MaskedArray returns an Array (and thus does not contain the mask member. If you cast it to a MaskedArray the original mask is lost).
A workaround for your issue could be using containment instead of inheritance:
class MaskedArray {
private :
Array array;
bool *mask; // this holds the boolean mask of the array
public :
MaskedArray operator+ ( double value ) const {
// return a new MaskedArray with the argument added to each element
}
// delegate public functions
}
Ofcourse, now MaskedArray can't use the protected members of Array (in a lot of cases, this is a good thing) and the public interface must be delegated.
First, your reported error about covariant result is not consistent with the presented code.
It only appears for virtual member functions, and in the presented code, as I write this, there is no such.
Do not in the future waste our time again by asking about what's wrong with your real code, and presenting some made up fantasy code.
Anyway, cure: in your real code, just remove the word virtual.
Also, word of advice: use a std::vector to hold the data and take care of allocation, copying and deallocation.

c++ overloaded method in derived class

I have the following question:
Assume base class A with method:
A& operator+(A& a) {...}
I also have a derived class B which overloads (or at least it should so) this method:
A& operator+(B& b) {...}
The problem is that if i want to call something like:
b + a (where b is of type B and a of type A) i get a compile error.
(error C2679: binary '+' : no operator found which takes a right-hand operand of type 'A' (or there is no acceptable conversion)).
Shouldnt that call the base class method? (it looks like it overrides the method..)
If not, why? Is there a way to fix this (dont tell me to overload the method in B with A&)
Sorry i dont give examples in formated text, but i dont know how to format it.
Thanks in advance!
PS Im using Visual studio 2010 beta.
No, it won't call the base class function. Class B has an operator+, it doesn't take the correct parameter, end of story.
You can define operator+ as a free function, not in any class. Perhaps a friend, if it needs to access private data:
A operator+(const A &lhs, const A &rhs) { ... }
B operator+(const B &lhs, const B &rhs) { ... }
Then b + a will call the first operator, as will a + b. b + b will call the second.
Alternatively, you could "un-hide" the base class implementation, by putting this in class B:
using A::operator+;
it's probably best not to, though. Most operators work better as free functions, because then you get automatic conversions on both operands. C++ never performs conversions on the LHS of a member function call.
Btw, operator+ almost certainly should return by value, not by reference, since an automatic (stack) variable no longer exists once the function returns. So the caller needs to be passed a copy of the result, not a reference to it. For this reason operator+ and inheritance aren't a great mix, although it can probably work as long as the caller knows what they're doing.
The problem is called hiding - a member function in a derived class hides functions with the same name in the base class. In this case you can't access A::operator+(A&) because it's being hidden by B::operator+. The way to fix this is to define B::operator+(A&), and possibly have it call the base class function.
Edit: There's a section in the C++ FAQ Lite that goes into more detail about this problem and offers another possible solution, namely the using keyword.
The problem is that you are defining the member operator, so when called as b + a it results in b.operator+( a ), which doesn't exist.
Accepted practice is to define free operators that themselves would call [virtual] members on the arguments.
Edit:Standard example of what I'm talking about is adapting a class hierarchy for output streaming:
class base
{
public:
virtual ~base();
virtual void print( std::ostream& ) const;
};
std::ostream& operator<<( std::ostream& out, const base& b )
{
b.print( out ); return out;
}
This doesn't really work for math operations since you want to return by [const] value, not reference, i.e. avoid nonsense like a + b = c;.
For example, addition of real and complex numbers is defined, but yields complex number as the result, so you cannot derive complex from real. The other way - maybe. But still you want to define exact operations interface:
const real operator+( const real&, const real& );
const complex operator+( const complex&, const complex& );
Hope this gives you enough to re-think your design :)
Couple of things come to mind. First, you would generally want to make the operator + "virtual". Then, the derived operator + taking a reference to B would be an override due to co-variance, instead of hiding the base class implementation, which is what is happening here.
That said, I suspect (but can't say for certain without compiling a test project) that that would actually solve your problem. That's because the standard answer for binary operators is to use static methods that take two parameters on the class. The C++ STL uses this technique extensively, and I don't know of a reason to attempt to implement binary operators as instance methods, virtual or not. It's just too confusing, with no real up-side.