Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I override operators in C++?

Tags:

c++

oop

c++11

I knew that we can overload operators for a class. But my question is whether I can override operators?

Let us consider that I have a base class and derived class, is it possible to override an operator defined ( overloaded ) in the base class in the derived class (as with function overriding)?

like image 730
Venkatesh Avatar asked Sep 26 '14 19:09

Venkatesh


People also ask

Can operators be overridden?

You can override operators, but they might not do what you want. The reason is that operators (actually overloads in general) are selected from the static type of an object. If you now have a reference-to-base which is bound to a derived instance, it will not call the operator for the derived class.

Which operators Cannot be overridden?

Operators that cannot be overloaded in C++ For an example the sizeof operator returns the size of the object or datatype as an operand. This is evaluated by the compiler. It cannot be evaluated during runtime. So we cannot overload it.

Does C support operator overloading?

This feature is present in most of the Object Oriented Languages such as C++ and Java. But C doesn't support this feature not because of OOP, but rather because the compiler doesn't support it (except you can use _Generic).

Can we overload only existing operator?

Rules for Operator Overloading:You can only overload existing operators. You can't overload new operators. Some operators cannot be overloaded using a friend function. However, such operators can be overloaded using member function.


2 Answers

You can achieve the desired effect by providing a "cover" virtual function in the base class, and call it from the operator's implementation in the base class:

struct Base {
    Base operator+(const Base& other) {
        return add(other);
    }
protected:
    virtual Base add(const Base& other) {
        cout << "Adding in Base's code." << endl;
        return Base();
    }
};

struct Derived : public Base {
protected:
    virtual Base add(const Base& other) {
        cout << "Adding in Derived's code." << endl;
        return Derived();
    }
};

int main() {
    Base b1;
    Base b2;
    Derived d1;
    Derived d2;
    Base res;
    res = b1+b2; // Prints "Adding in Base's code."
    res = b1+d2; // Prints "Adding in Base's code."
    res = d1+b2; // Prints "Adding in Derived's code."
    res = d1+d2; // Prints "Adding in Derived's code."
    return 0;
}

Demo.

like image 161
Sergey Kalinichenko Avatar answered Oct 22 '22 09:10

Sergey Kalinichenko


An overloaded operator is just a function, so it can be virtual, and overridden.

But it's seldom a good idea.

Consider an overridden copy assignment operator, that in some derived class checks whether the value to be assigned is compatible with the object assigned to. Effectively it has replaced static type checking with dynamic type checking, which involves a lot of laborous testing and only a statistical chance of correctness.


Example of ungoodness:

#include <assert.h>
#include <iostream>
#include <string>
using namespace std;

struct Person
{
    string name;

    virtual
    auto operator=( Person const& other )
        -> Person&
    { name = other.name; return *this; }

    Person( string const& _name ): name( _name ) {}
};

struct Employee: Person
{
    int     id;

    auto operator=( Person const& other )
        -> Person&
        override
    {
        auto& other_as_employee = dynamic_cast<Employee const&>( other );

        Person::operator=( other );
        id =  other_as_employee.id;
        return *this;
    }

    auto operator=( Employee const& other )
        -> Employee&
    {
        return static_cast<Employee&>(
            operator=( static_cast<Person const&>( other ) )
            );
    }

    Employee( string const& _name, int const _id )
        : Person( _name )
        , id( _id )
    {}
};

void foo( Person& someone )
{
    someone = Person( "Maria" );        // Fails, probably unexpectedly.
}

auto main() -> int
{
    Person&& someone = Employee( "John", 12345 );
    foo( someone );
}
like image 44
Cheers and hth. - Alf Avatar answered Oct 22 '22 09:10

Cheers and hth. - Alf