answersLogoWhite

0


Best Answer

The assignment operator overload is a typical example of operator overloading. Every class of object has an assignment operator by default, which simply assigns the value of the members of an existing class to the members of another existing class. The two classes may even be the same class. However, the default implementation is not suitable for classes that contain pointers to memory that cannot be shared with other classes. Assigning the value of one pointer to another simply copies the pointer's value (a shallow copy) but not what it points at (a deep copy). Thus the assignment operator must be overloaded to perform a deep-copy, as per the following example:

struct X {

// destructor

~X(){ delete( m_pointer ); }

// default constructor

X(): m_pointer( new int(100) ){}

// copy constructor

X( const X& x): m_pointer( x.m_pointer ? new int( *x.m_pointer) : NULL ) {}

// assignment operator overload

X& operator= ( const X& x );

int* m_pointer;

};

X& X::operator= ( const X& x )

{

if( this != &x ) // test for self-reference

{delete( m_pointer );m_pointer = x.m_pointer ? new int(*x.m_pointer) : NULL;}

return( *this );

}

In the above example, the assignment operator overload first checks to ensure that the incoming object is not a self-reference. If it is not, then we release the current allocation and create a new allocation, copying the incoming object's memory by value. If we had not checked for a self-reference, then we could easily end up deleting the very memory we wished to copy, such as in the following example:

X x;

X* y = &x;

x = *y; // self-assignment

In the above example, x and *y are obviously references to the same object, but it may not be quite so obvious if the assignment occurred elsewhere in our code. Therefore the object's assignment operator overload must cater for this eventuality and veto the assignment -- thus leaving the original object unchanged.

The assignment operator can also be overloaded in order to prevent assignment. You would do this if the object were intended to act as a singleton, for instance. In this case we simply need to declare the operator as private to the class but do not need to provide any implementation. Alternatively, we can simply return a reference to the current instance:

X& operator= ( const X& x ) { return( *this ); }

No other operator has a default implementation when applied to classes, therefore if we want to make use of other operators upon our classes, such as +, ++ or +=, then we must overload them in the class declaration. Again, each overload must test for self-references and act accordingly. However, while there's nothing to prevent you from providing a completely unique implementation of these operators, common sense dictates that all such implementations must be intuitive and predictable. While it may be fun to implement the plus operator as a minus operation, it has no practical value in the real world -- it is neither intuitive nor predictable.

The stream insertion (<<) and extraction (>>) operators are another typical example of operator overloading. These cannot be implemented within the class itself because the l-value of these operators must be a stream, while internal class operator overloads use the current instance of the class as the l-value. Therefore these operators must be implemented outside of the class.

Many programmers implement these "external" operators as friend functions. While some do have valid reasons for doing so, if the public class interface provides everything required of these operators then there is no need to declare the operator as a friend function. Although some programmers continually claim friendship undermines encapsulation this is not the case at all. Friends simply extend the class interface, nothing more. However, if the underlying class implementation is altered, all friend functions may need to be updated to cater for these changes -- which increases the maintenance cost. Therefore, if operator overloads can be implemented with friend access, then your class becomes that much easier to maintain.

Here's a typical example of an external operator implemented as a friend function:

struc X

{

friend ostream& operator<<( const X& x );

private:

int m_data;

};

ostream& operator<<( ostream& os, const X& x )

{

os << x.m_data;

return( os );

}

Now here's the same operator overload implemented without a friend function:

struc X

{

int GetData() const { return( m_data ); }

private:

int m_data;

};

ostream& operator<<( ostream& os, const X& x )

{

os << x.GetData();

return( os );

}

While there's clearly the need for an extra function call, that call is completely eliminated by virtue of the fact X::GetData() will be inline expanded by the compiler. Thus the latter will not affect performance in any way. However, the main advantage of the non-friend function comes when you later decide to alter the implementation of the class:

struc X

{

int GetData() const { return(( int ) m_data ); }

private:

double m_data;

};

Here we've changed the member variable to a double, but the GetData() accessor method still returns an int. The accessor is therefore an abstraction, thus the insertion operator overload is left unaffected by the internal change to the class. However, had we made this same change in the earlier example employing the friend function, there is no abstraction and the extraction operator will insert a double into the output stream. If this were undesirable then we'd have to alter the friend function as well. Not only have we increased the maintenance, we've completely undermined the abstraction of our class. Note that we have not undermined the encapsulation (as some would claim), only the abstraction has been undermined. Thus if you want to retain the abstraction, do not use a friend function. Friend functions should only be used when abstraction is not an issue, and the function genuinely requires access to the private members of the class.

User Avatar

Wiki User

10y ago
This answer is:
User Avatar
More answers
User Avatar

Wiki User

14y ago

There are two ways to overload an operator in C++: in a class or globally. Some operators can only be defined inside a class, others can only be defined globally, and still others can be defined either way.

To overload the + operator for a class:

class A {
public:
...
A(int i) : value(i) {}
...
A operator+(const A& a) {
return A(value + a.value);

}
...

private:
int value;

};


Or, equivalently:

class A {
public:
...
A(int i) : value(i) {}
...
friend A operator+(const A&, const A&);
...

private:
int value;

};

A operator+(const A& a, const A& b) {
return A(a.value + b.value);

}


For expressions a and b of type A and an expression i of type int:

To define (a + i), overload A A::operator+(int) or A operator+(const A&, int).
To define (i + a), overload A operator+(int, const A&).
To define (-a), overload A A::operator-().
To define (a = b), overload A& A::operator=(const A&).

Et cetera.

This answer is:
User Avatar

User Avatar

Wiki User

9y ago

Operator overloading provides the means to enable a conventional and intuitive notation when applied to user-defined types. Instead of invoking functions to operate upon those types, you can use operator overloads instead.

For instance, the std::string class overloads the binary addition operator to provide string concatenation. Thus instead of calling a C-style function such as concat(a,b) you invoke the operator directly using a + b.

Some operators are not overloaded for certain types. For instance, std::vector does not support the addition operator, even though std::string and std::vector both implement arrays. This is because there is no intuitiveness to the addition operator when applied to vectors. Unlike a string where concatenation is the only obvious intent of the addition operator, adding to vectors means different things to different people; do we add the elements together or do we append the elements? If the operation is not obvious to the programmer let alone the reader, then we must not implement it, we must use a named function instead.

The following code demonstrates the correct way to implement the comparison operators to determine the relationship between two instances of the class, as well as basic arithmetic operator overloads.

The two friend operators are required because the insertion operator must be declared external (it is a function of the output stream class, not the X class) and both friends require private access to the X class.

Note how all the relationship operators are expressed in terms of the less-than operator (friend). You don't have to do it this way, but it has the advantage that you only need one friend function rather than all six. Note also that not all operators need be implemented as members, only those that directly assign to the object need be members. Again, you don't have to do it this way, but by keeping them external you not only simplify the X interface you gain the benefit of auto-conversion of both operands (member operators can only convert the rhs value).

#include

#include

#include

// Interface of X

class X

{

public: // Construction and assignement

X (int = 0, float = 0.0); // default constructor

X (const X&); // copy constructor

X (X&&); // move constructor

X& operator= (const X&); // copy assignement operator

X& operator= (X&&); // move assignement operator

public: // Compound assignment operator overloads

X& operator+= (const X&); // add assignment operator

X& operator-= (const X&); // subtract assignment operator

X& operator*= (const X&); // multiply assignment operator

X& operator/= (const X&); // divide assignment operator

private: // attributes

int a;

float b;

// friend functions

friend bool operator< (const X&, const X&);

friend std::ostream& operator<< (std::ostream&, const X&);

};

// implementation of X (construction and assignment)

X::X (int i, float f): a {i}, b {f} {}

X::X (const X& rhs): a {rhs.a}, b {rhs.b} {}

X::X (X&& rhs): a {std::move (rhs.a)}, b {std::move (rhs.b)} {}

X& X::operator= (const X& rhs) { a = rhs.a; b = rhs.b; return *this; }

X& X::operator= (X&& rhs) { a = std::move (rhs.a); b = std::move (rhs.b); return *this; }

// implementation of X (compound arithmetic)

X& X::operator+= (const X& rhs) { a += rhs.a; b += rhs.b; return *this;}

X& X::operator-= (const X& rhs) { a -= rhs.a; b -= rhs.b; return *this;}

X& X::operator*= (const X& rhs) { a *= rhs.a; b *= rhs.b; return *this;}

X& X::operator/= (const X& rhs) {

if (!rhs.a !rhs.b)

throw std::out_of_range ("X::operator/ divide by zero!");

a /= rhs.a; b /= rhs.b; return *this;

}

// external functions...

// all the relational operators are expressed in terms of the less-than operator

bool operator< (const X& lhs, const X& rhs) { return lhs.a < rhs.a (!(rhs.a < lhs.a) && lhs.b < rhs.b); }

bool operator<= (const X& lhs, const X& rhs) { return lhs < rhs !(rhs < lhs); }

bool operator> (const X& lhs, const X& rhs) { return rhs < lhs && !(lhs < rhs); }

bool operator>= (const X& lhs, const X& rhs) { return rhs < lhs !(lhs < rhs); }

bool operator== (const X& lhs, const X& rhs) { return !(lhs < rhs) && !(rhs < lhs); }

bool operator!= (const X& lhs, const X& rhs) { return lhs < rhs rhs < lhs; }

// arithmetic operator overloads (expressed in terms of compound assignments)

X operator+ (const X& lhs, const X& rhs) { X t {lhs}; t += rhs; return t; }

X operator- (const X& lhs, const X& rhs) { X t {lhs}; t -= rhs; return t; }

X operator* (const X& lhs, const X& rhs) { X t {lhs}; t *= rhs; return t; }

X operator/ (const X& lhs, const X& rhs) { X t {lhs}; t /= rhs; return t; }

// output stream insertion operator overload for type X

std::ostream& operator<< (std::ostream& os, const X& x)

{

os << "X{" << x.a << "," << x.b << "}";

return os;

}

// relationship tester

void test_relationships (const X& a, const X& b)

{

using std::cout;

using std::endl;

cout << a << " < " << b << " = " << (a < b ? "true " : "false") << '\n';

cout << a << " <= " << b << " = " << (a <= b ? "true " : "false") << '\n';

cout << a << " > " << b << " = " << (a > b ? "true " : "false") << '\n';

cout << a << " >= " << b << " = " << (a >= b ? "true " : "false") << '\n';

cout << a << " == " << b << " = " << (a == b ? "true " : "false") << '\n';

cout << a << " != " << b << " = " << (a != b ? "true " : "false") << endl;

}

// arithmetic tester

void test_arithmetic (const X& a, const X& b)

{

using std::cout;

using std::endl;

cout << a << " + " << b << " = " << (a + b) << '\n';

cout << a << " - " << b << " = " << (a - b) << '\n';

cout << a << " * " << b << " = " << (a * b) << '\n';

try

{

cout << a << " / " << b << " = " << (a / b);

}

catch (std::out_of_range& e)

{

std::cout << e.what();

}

cout << endl;

}

// test-driver

int main ()

{

X x[4] {{0, 0.1F}, {1, 0.1F}, {1, 0.1F}, {0, 0.1F}};

for (auto a : x)

{

for (auto b : x)

{

test_relationships (a, b);

}

}

for (auto a : x)

{

for (auto b : x)

{

test_arithmetic (a, b);

}

}

}

Example Output

X{0,0.1} < X{0,0.1} = false

X{0,0.1} <= X{0,0.1} = true

X{0,0.1} > X{0,0.1} = false

X{0,0.1} >= X{0,0.1} = true

X{0,0.1} == X{0,0.1} = true

X{0,0.1} != X{0,0.1} = false

X{0,0.1} < X{1,0.1} = true

X{0,0.1} <= X{1,0.1} = true

X{0,0.1} > X{1,0.1} = false

X{0,0.1} >= X{1,0.1} = false

X{0,0.1} == X{1,0.1} = false

X{0,0.1} != X{1,0.1} = true

X{0,0.1} < X{1,0.1} = true

X{0,0.1} <= X{1,0.1} = true

X{0,0.1} > X{1,0.1} = false

X{0,0.1} >= X{1,0.1} = false

X{0,0.1} == X{1,0.1} = false

X{0,0.1} != X{1,0.1} = true

X{0,0.1} < X{0,0.1} = false

X{0,0.1} <= X{0,0.1} = true

X{0,0.1} > X{0,0.1} = false

X{0,0.1} >= X{0,0.1} = true

X{0,0.1} == X{0,0.1} = true

X{0,0.1} != X{0,0.1} = false

X{1,0.1} < X{0,0.1} = false

X{1,0.1} <= X{0,0.1} = false

X{1,0.1} > X{0,0.1} = true

X{1,0.1} >= X{0,0.1} = true

X{1,0.1} == X{0,0.1} = false

X{1,0.1} != X{0,0.1} = true

X{1,0.1} < X{1,0.1} = false

X{1,0.1} <= X{1,0.1} = true

X{1,0.1} > X{1,0.1} = false

X{1,0.1} >= X{1,0.1} = true

X{1,0.1} == X{1,0.1} = true

X{1,0.1} != X{1,0.1} = false

X{1,0.1} < X{1,0.1} = false

X{1,0.1} <= X{1,0.1} = true

X{1,0.1} > X{1,0.1} = false

X{1,0.1} >= X{1,0.1} = true

X{1,0.1} == X{1,0.1} = true

X{1,0.1} != X{1,0.1} = false

X{1,0.1} < X{0,0.1} = false

X{1,0.1} <= X{0,0.1} = false

X{1,0.1} > X{0,0.1} = true

X{1,0.1} >= X{0,0.1} = true

X{1,0.1} == X{0,0.1} = false

X{1,0.1} != X{0,0.1} = true

X{1,0.1} < X{0,0.1} = false

X{1,0.1} <= X{0,0.1} = false

X{1,0.1} > X{0,0.1} = true

X{1,0.1} >= X{0,0.1} = true

X{1,0.1} == X{0,0.1} = false

X{1,0.1} != X{0,0.1} = true

X{1,0.1} < X{1,0.1} = false

X{1,0.1} <= X{1,0.1} = true

X{1,0.1} > X{1,0.1} = false

X{1,0.1} >= X{1,0.1} = true

X{1,0.1} == X{1,0.1} = true

X{1,0.1} != X{1,0.1} = false

X{1,0.1} < X{1,0.1} = false

X{1,0.1} <= X{1,0.1} = true

X{1,0.1} > X{1,0.1} = false

X{1,0.1} >= X{1,0.1} = true

X{1,0.1} == X{1,0.1} = true

X{1,0.1} != X{1,0.1} = false

X{1,0.1} < X{0,0.1} = false

X{1,0.1} <= X{0,0.1} = false

X{1,0.1} > X{0,0.1} = true

X{1,0.1} >= X{0,0.1} = true

X{1,0.1} == X{0,0.1} = false

X{1,0.1} != X{0,0.1} = true

X{0,0.1} < X{0,0.1} = false

X{0,0.1} <= X{0,0.1} = true

X{0,0.1} > X{0,0.1} = false

X{0,0.1} >= X{0,0.1} = true

X{0,0.1} == X{0,0.1} = true

X{0,0.1} != X{0,0.1} = false

X{0,0.1} < X{1,0.1} = true

X{0,0.1} <= X{1,0.1} = true

X{0,0.1} > X{1,0.1} = false

X{0,0.1} >= X{1,0.1} = false

X{0,0.1} == X{1,0.1} = false

X{0,0.1} != X{1,0.1} = true

X{0,0.1} < X{1,0.1} = true

X{0,0.1} <= X{1,0.1} = true

X{0,0.1} > X{1,0.1} = false

X{0,0.1} >= X{1,0.1} = false

X{0,0.1} == X{1,0.1} = false

X{0,0.1} != X{1,0.1} = true

X{0,0.1} < X{0,0.1} = false

X{0,0.1} <= X{0,0.1} = true

X{0,0.1} > X{0,0.1} = false

X{0,0.1} >= X{0,0.1} = true

X{0,0.1} == X{0,0.1} = true

X{0,0.1} != X{0,0.1} = false

X{0,0.1} + X{0,0.1} = X{0,0.2}

X{0,0.1} - X{0,0.1} = X{0,0}

X{0,0.1} * X{0,0.1} = X{0,0.01}

X::operator/ divide by zero!

X{0,0.1} + X{1,0.1} = X{1,0.2}

X{0,0.1} - X{1,0.1} = X{-1,0}

X{0,0.1} * X{1,0.1} = X{0,0.01}

X{0,0.1} / X{1,0.1} = X{0,1}

X{0,0.1} + X{1,0.1} = X{1,0.2}

X{0,0.1} - X{1,0.1} = X{-1,0}

X{0,0.1} * X{1,0.1} = X{0,0.01}

X{0,0.1} / X{1,0.1} = X{0,1}

X{0,0.1} + X{0,0.1} = X{0,0.2}

X{0,0.1} - X{0,0.1} = X{0,0}

X{0,0.1} * X{0,0.1} = X{0,0.01}

X::operator/ divide by zero!

X{1,0.1} + X{0,0.1} = X{1,0.2}

X{1,0.1} - X{0,0.1} = X{1,0}

X{1,0.1} * X{0,0.1} = X{0,0.01}

X::operator/ divide by zero!

X{1,0.1} + X{1,0.1} = X{2,0.2}

X{1,0.1} - X{1,0.1} = X{0,0}

X{1,0.1} * X{1,0.1} = X{1,0.01}

X{1,0.1} / X{1,0.1} = X{1,1}

X{1,0.1} + X{1,0.1} = X{2,0.2}

X{1,0.1} - X{1,0.1} = X{0,0}

X{1,0.1} * X{1,0.1} = X{1,0.01}

X{1,0.1} / X{1,0.1} = X{1,1}

X{1,0.1} + X{0,0.1} = X{1,0.2}

X{1,0.1} - X{0,0.1} = X{1,0}

X{1,0.1} * X{0,0.1} = X{0,0.01}

X::operator/ divide by zero!

X{1,0.1} + X{0,0.1} = X{1,0.2}

X{1,0.1} - X{0,0.1} = X{1,0}

X{1,0.1} * X{0,0.1} = X{0,0.01}

X::operator/ divide by zero!

X{1,0.1} + X{1,0.1} = X{2,0.2}

X{1,0.1} - X{1,0.1} = X{0,0}

X{1,0.1} * X{1,0.1} = X{1,0.01}

X{1,0.1} / X{1,0.1} = X{1,1}

X{1,0.1} + X{1,0.1} = X{2,0.2}

X{1,0.1} - X{1,0.1} = X{0,0}

X{1,0.1} * X{1,0.1} = X{1,0.01}

X{1,0.1} / X{1,0.1} = X{1,1}

X{1,0.1} + X{0,0.1} = X{1,0.2}

X{1,0.1} - X{0,0.1} = X{1,0}

X{1,0.1} * X{0,0.1} = X{0,0.01}

X::operator/ divide by zero!

X{0,0.1} + X{0,0.1} = X{0,0.2}

X{0,0.1} - X{0,0.1} = X{0,0}

X{0,0.1} * X{0,0.1} = X{0,0.01}

X::operator/ divide by zero!

X{0,0.1} + X{1,0.1} = X{1,0.2}

X{0,0.1} - X{1,0.1} = X{-1,0}

X{0,0.1} * X{1,0.1} = X{0,0.01}

X{0,0.1} / X{1,0.1} = X{0,1}

X{0,0.1} + X{1,0.1} = X{1,0.2}

X{0,0.1} - X{1,0.1} = X{-1,0}

X{0,0.1} * X{1,0.1} = X{0,0.01}

X{0,0.1} / X{1,0.1} = X{0,1}

X{0,0.1} + X{0,0.1} = X{0,0.2}

X{0,0.1} - X{0,0.1} = X{0,0}

X{0,0.1} * X{0,0.1} = X{0,0.01}

X::operator/ divide by zero!

This answer is:
User Avatar

User Avatar

Wiki User

14y ago
Operator overloading

The mechanism of giving special meanings to an operator is known as operator overloading.It provides a flexible option for the creation of new definitions for most of the C++ operators. we can almost create a new language of our own by the creative use of the function and operator overloading techniques.

This answer is:
User Avatar

User Avatar

Wiki User

10y ago

Operator overloading in any language is a means of providing a new implementation for a built-in operator. Virtually every class of object you create should support the assignment operator (=) and all of the comparison operators (==, !=, <, <=, > and >=), therefore these should almost always be overloaded. If your class can easily be inserted or extracted from a stream (or a particular type of stream) then you should provide insertion and extraction operator overloads (<< and >>) for those streams. If your class can be easily converted to other classes or primitive data types, then you should also provide conversion operators for those types. If your class is intrinsically numeric, you should also overload all the standard arithmetic operators (+, +=, -, -=, *, *=, / and /=). Bitwise operators (^, ^=, &, &=, |, |= and !) should only be provided wherever it makes sense to do so.

Ultimately, you should only provide operator overloads where their usage would be intuitive and predictable. If their usage is ambiguous, use a user-defined function instead. Every operator overload should also be implemented by calling user-defined functions. The operators then simply act as syntactic sugar making it easier to use your class.

This answer is:
User Avatar

User Avatar

Wiki User

10y ago

In C++, operators such as + (plus) and - (minus) are overloaded to work with any combination of primitive types, including integrals and floating point values. The overloads are such that primitives are automatically promoted to the highest resolution. Thus if you add a long and a short, the return value is a long, while adding a float and an int returns a float.

However, sometimes it can be useful to overload these operators to cater for other types. For instance, if you have a class or structure that encapsulates a fruit and its price, adding a primitive to a fruit object could return a float that is the sum of the primitive and the fruit's price:

struct fruit

{

std::string name;

float price;

};

float operator+ (const fruit& o, const float f){ return( o.price + f ); }

float operator+ (const float f, const fruit& o){ return( o.price + f ); }

int main()

{

fruit a;

a.name="apple";

a.price=0.12;

float f = a + 0.02; // call operator overload

assert( f 0.15 );

}

This answer is:
User Avatar

User Avatar

Wiki User

12y ago

Operators are symbols that work with operands.

Here are the most common operators in C++:

Assignment operator:

= (assign)

Arithmetic operators:

+ (add)

- (subtract)

* (multiply, also used for indirection)

/ (divide)

% (modus)

Arithmetic assignment (compound) operators:

+= (plus assign)

-= (subtract assign)

*= (multiply assign)

/= (divide assign)

%= (modus assign)

Bit-shift operators (also used for redirection):

>> (shift right)

<< (shift left)

Bit-shift assignment (compound) operators:

>>= (shift right assign)

<<= (shift left assign)

Bitwise operators:

! (NOT)

& (AND, also used for dereferencing)

| (OR)

^ (XOR)

Bitwise assignment (compound) operators:

&= (AND assign)

|= (OR assign)

^= (XOR assign)

Comma operator:

, (sequence point, also used to separate parameters and class initialisation lists))

Conditional operators (e.g., <condition> ? <statement_1> : <statement_2>):

? (execute statement_1 when condition is true)

: (execute statement_2 when condition is false)

Dereference operator:

& (dereference, also used for bitwise AND)

Element operator:

[] (declare an array, or access an element of an array)

Equality operators:

== (is equal)

!= (is not equal)

Indirection operator:

* (return value, also used for multiply)

Increment and decrement operators:

++ (postfix and prefix increment)

-- (postfix and prefix decrement)

Logical comparison operators:

&& (AND)

(OR)

Member access operators:

. (direct access)

--> (indirect access)

[Edit - reformatted and reclassified]

This answer is:
User Avatar

User Avatar

Wiki User

10y ago

The result of an operator overload must be predictable and logical, according to the built-in implementation of the operator. There must be no ambiguity, they must be intuitive. While it can be fun to implement subtraction using the plus operator, consumers of your objects will find your code untrustworthy.

Operators that should almost always be overloaded include the comparison operators (==, !=, <, <=, > and >=) which will allow two objects of the exact same type to be compared. You can also provide comparisons between different objects, but the comparison must be entirely logical. For instance, comparing a primitive int with an object would make no sense unless the object fundamentally represented a numeric value.

The assignment operator should only be overloaded if the compiler-generated assignment operator is insufficient, such as when you need to deep-copy member pointers.

Conversion operators should be provided whenever possible, particularly if your object can be easily converted to and from a primitive or string object. However, when an object can be converted to two or more fundamentally different types, it is rarely a good idea to also provide stream insertion and extraction operators; consumers will find explicit conversions more predictable.

If your object cannot be converted to a primitive numeric value, then it is highly unlikely the arithmetic operators and bitwise comparisons will make any sense to consumers either.

If in any doubt whatsoever, do not provide an operator. Use a well-defined function instead. But wherever an operation can unambiguously be regarded as being intuitive, implement the operator such that it calls the well-defined function.

This answer is:
User Avatar

User Avatar

Wiki User

12y ago

It is a non-existent term. Objects cannot be overloaded. Only functions can be overloaded.

This answer is:
User Avatar

Add your answer:

Earn +20 pts
Q: How to overloade operater in c plus plus?
Write your answer...
Submit
Still have questions?
magnify glass
imp
Continue Learning about Engineering