Operator [ ] overloading with const and non const versions
Whether or not you need two overloads depends on what interface you want to provide.
If you want to be able to modify elements even in const
instances of Array
, then yes, the single int& operator[](int index) const;
is enough. This is what std::unique_ptr
does.
But if you want elements of const
Array
s to be read-only, and at the same time elements of non-const
Array
s to be mutable, you need two overloads. std::vector
does that.
Usually the second option is preferred.
Array operator [] overloading const and non-const versions
The non-const function will always be called on a non-const array, and the const function on a const array.
When you have two methods with the same name, the compiler selects the best-fitting one based on the type of the arguments, and the type of the implicit object parameter (arr).
I just answered a similar question the other day, you may find it helpful: https://stackoverflow.com/a/16922652/2387403
C++ overload operator twice, one return non-const reference and the other const reference, what is the preference?
These functions don't overload each other; they have the same signatures, and so the attempt to redefine the same function, which is an error. The return type is not part of a function's signature. To overload a function, you must declare a second function with the same name, but different parameters or const
/volatile
qualifiers - that is, qualifiers on the function, not the return type.
(They don't override each other either; overriding is what derived classes do to their base classes' virtual functions).
It's common to define a const
and a non-const
overload of a member function; the const
overload must declare the function const
, not just the return type:
T& operator()(par_list){blablabla}
const T& operator()(par_list) const {blablabla}
^^^^^
Now the first will be called if you apply ()
to a non-const
object, and the second on a const
object. For example:
Thingy nc;
Thingy const c;
nc(); // calls the first (non-const) overload
c(); // calls the second (const) overload
what does const mean when overloading operator in C++
It can be used for any member function, not only operators. It means, that this function will:
- not be able to modify any data members (except
mutable
ones) - will not be able to call any non-
const
member functions
why must you provide the keyword const in operator overloads
A const
parameter is const throughout the function using it, it does not change its constness outside of it.
In this case you want to declare a const argument so that your assignment operator accepts both non-const variables and const variables; the latter case, in particular, includes the result of expressions, which is a temporary const variable and which you generally want to support in assignments.
Force compiler to choose const operator overload
It doesn't have anything to do with the array being dynamically allocated. Your variable a
is not const
, so the non-const
function will be called on it. If you had const B b(10);
and did b[3]
, the const
version would be called.
If you really want to, you can force the const
version to be called by casting to a const
reference:
static_cast<const A&>(a)[3]
(Or alternatively, create a reference variable and call it on that)
C++ operator + and * non-const overloading
You can use proxies instead of real values, and proxies can be constant, as they are not going to be changed. Below is a small example of how it might look like. Be aware that all the temporaries are still going to be created in that example but if you want to be smart, you can just save the operations, not the actual results of operations, and calculate only when someone wants to finally get result or a part of it. It might even speed up your code enormously as it helped APL
Also, you might want to make most of the members private.
#include <memory>
#include <iostream>
struct FunctionTreeProxy;
struct FunctionTree;
struct FunctionTreeProxy {
mutable std::auto_ptr<FunctionTree> ft;
explicit FunctionTreeProxy(FunctionTree * _ft): ft(_ft) {}
FunctionTreeProxy(FunctionTreeProxy const & rhs): ft(rhs.ft) {}
FunctionTreeProxy operator+(FunctionTree & rhs);
FunctionTreeProxy operator*(FunctionTree & rhs);
FunctionTreeProxy operator+(FunctionTreeProxy const & rhs);
FunctionTreeProxy operator*(FunctionTreeProxy const & rhs);
};
struct FunctionTree {
int i;
FunctionTree(int _i): i(_i) {}
FunctionTree(FunctionTreeProxy const & rhs): i(rhs.ft->i) {}
FunctionTree * add(FunctionTree & rhs) {
return new FunctionTree(i + rhs.i);
}
FunctionTree * mult(FunctionTree & rhs) {
return new FunctionTree(i * rhs.i);
}
FunctionTreeProxy operator+(FunctionTree & rhs) {
return FunctionTreeProxy(add(rhs));
}
FunctionTreeProxy operator*(FunctionTree & rhs) {
return FunctionTreeProxy(mult(rhs));
}
FunctionTreeProxy operator+(FunctionTreeProxy const & rhs) {
return FunctionTreeProxy(add(*rhs.ft));
}
FunctionTreeProxy operator*(FunctionTreeProxy const & rhs) {
return FunctionTreeProxy(mult(*rhs.ft));
}
};
FunctionTreeProxy FunctionTreeProxy::operator+(FunctionTree & rhs) {
return FunctionTreeProxy(ft.get()->add(rhs));
}
FunctionTreeProxy FunctionTreeProxy::operator*(FunctionTree & rhs) {
return FunctionTreeProxy(ft.get()->mult(rhs));
}
FunctionTreeProxy FunctionTreeProxy::operator+(FunctionTreeProxy const & rhs) {
return FunctionTreeProxy(ft.get()->add(*rhs.ft));
}
FunctionTreeProxy FunctionTreeProxy::operator*(FunctionTreeProxy const & rhs) {
return FunctionTreeProxy(ft.get()->mult(*rhs.ft));
}
int main(int argc, char* argv[])
{
FunctionTree a(1), b(2), c(3);
FunctionTree z = a + b * c;
std::cout << z.i << std::endl;
return 0;
}
Related Topics
C++: Deep Copying a Base Class Pointer
Configuring the Gcc Compiler Switches in Qt, Qtcreator, and Qmake
Get Absolute Value Without Using Abs Function Nor If Statement
Checking for Eof in String::Getline
Unique Hardware Id in MAC Os X
Which <Type_Traits> Cannot Be Implemented Without Compiler Hooks
How to Define Several Include Path in Makefile
Why Explicitly Delete the Constructor Instead of Making It Private
Converting a Variable Name to a String in C++
Atomicity in C++:Myth or Reality
How to Deal with "Signed/Unsigned Mismatch" Warnings (C4018)
How to Tell Cmake to Use Clang on Windows
What's the Use of the Private Copy Constructor in C++
How to Provider User with Autocomplete Suggestions for Given Boost::Spirit Grammar