Operator= and Functions That Are Not Inherited in C++

operator= and functions that are not inherited in C++?

The assignment operator is technically inherited; however, it is always hidden by an explicitly or implicitly defined assignment operator for the derived class (see comments below).

(13.5.3 Assignment) An assignment operator shall be implemented by a
non-static member function with exactly one parameter. Because a copy
assignment operator operator= is implicitly declared for a a class if
not declared by the user, a base class assignment operator is always
hidden by the copy assignment operator of the derived class.

You can implement a dummy assignment operator which simply forwards the call to the base class operator=, like this:

// Derived class
template<typename T, unsigned int N> class Derived : public Base<Derived, T, N>
{
public:
template<typename T0, class = typename std::enable_if<std::is_convertible<T0, T>::value>::type>
inline Derived& operator=(const T0& rhs)
{
return Base<Derived, T, N>::operator=(rhs);
}
};

What's not inherited to a C++ Derived class? Apparently, operator= and some constructors are actually inherited

Dervied has no constructors, in this case a default constructor is generated which calls the default constructor of all base classes and members.

Similar things happen with the copy constructor and assignment operator. The Base class versions are being called by automatically generated Derived class versions.

This has nothing to do with inheritance of constructors or assignment operators.

Functions that do not automatically inherit

In fact, it is not correct to say that operator = is not inherited. The problem is that it is hidden by the implicitly-generated operator = for the derived class, so that (for instance), an assignment such as the one in the code below would be illegal:

A a;
B b;
b = a;

Since class B does not have any operator = accepting an A, but only an implicitly generated copy-assignment operator with the following signature:

B& operator = (B const&)

The situation is not different from the case of regular member functions in the derived class hiding member functions with the same name in the base class.

And as for regular member functions, you can have a using declaration in your class that makes the base class's operator = available:

class B: public A
{
public:
using A::operator =;
// ^^^^^^^^^^^^^^^^^^^^
};

This would make the assignment in the previous example compile.

Why does an overloaded assignment operator not get inherited?

Class Y contains implicitly-declared assignment operators, which hide the operator declared in the base class. In general, declaring a function in a derived class hides any function with the same name declared in a base class.

If you want to make both available in Y, use a using-declaration:

class Y : public X {
public:
using X::operator=;
};

Constructor, destructor, overloaded =operator function, copy constructor do not get inherited. What this exactly means?

What that statement is trying to say, is that class B does not automatically get a constructor B::B(int) when you add A::A(int). Similarly, B::operator=(int) is not automatically generated when you have A::operator=(int).

The copy constructor B::B(B const&) can be automatically generated, in which case it expects A::A(A const&). But you see from the argument that it's generated, not inherited as B::B(A const&).

The destructor works the same - generated, not inherited - but that's less visible because there's no parameter.

Why assignment operators of parent class are not accessible from derived class objects

The copy assignment operator is automatically generated in the derived class. This causes the base class's assignment operator to be hidden due to the regular name hiding rules of C++. You can unhide the name in the base class through the "using" directive. For example:

class C
{
public:
void operator =(int i) {}
};

class SubC : public C
{
public:
using C::operator=;
};

Why operator = doesn't get inherited from a template class

operator = is always hidden by the derived class implementation unless explicit using declaration is provided. This is true for both class templates and ordinary classes.

BTW, your declaration of operator= is very nonstandard. It is usually declared so for a class 'A'.

A& operator=(A const &);

Here is something that may be what you are looking for (and compiles)

template <class T> 
class TemplatePtr
{
public:
TemplatePtr& operator=(TemplatePtr const &)
{return *this;}
};

template<class T>
class TemplatePtr_ClassName: public TemplatePtr<T>
{
public:
~TemplatePtr_ClassName(){};
TemplatePtr_ClassName& operator=(TemplatePtr_ClassName const &that){
TemplatePtr<T>::operator=(that); // invoke base class assignment operator
return *this;
}
};

int main()
{
TemplatePtr_ClassName<int> data;
data = *new TemplatePtr_ClassName<int>;
// delete stuff
}

Trouble with inheritance of operator= in C++

If you do not declare copy-assignment operator in a class, the compiler will declare one for you implicitly. The implicitly declared copy-assignment operator will hide any inherited assignment operators (read about "name hiding" in C++), meaning that any inherited assignment operators will become "invisible" to the unqualified name lookup process (which is what happens when you do b = c), unless you take specific steps to "unhide" them.

In your case, class B has no explicitly declared copy-assignment operator. Which mean that the compiler will declare

B& B::operator =(const B&)

implicitly. It will hide the operator inherited from A. The line

b = c;

does not compile, because, the only candidate here is the above implicitly declared B::operator = (the compiler told you about that already); all other candidates are hidden. And since c is not convertible to B&, the above assignment does not compile.

If you want your code to compile, you can use using-declaration to unhide the inherited A::operator = by adding

using A::operator =;

to the definition of class B. The code will now compile, although it won't be a good style. You have to keep in mind that in this case the b = c assignment will invoke A::operator =, which assigns only the A portions of the objects involved. (But apparently that is your intent.)

Alternatively, in cases like this you can always work around name hiding by using a qualified version of the name

b.A::operator =(c);

C++: Using parent class operator function to update inherited variables of a child class object

Cube inherits the operator+ from Box. You don't need to implement it again in Cube.
But when removing the Cube operator+, you'll notice that C3 = C1 + C2; gives an error. C1 + C2 results in a Box-type, and you want to assign it to a Cube type. Her you should ask yourself a question: should C3 be a Cube type? If you add two cubes, will you get another cube? I don't think so. So C3 should be Box-type. Then the code works for me.

p.s.You also don't need the this->[member variable]. You already have access to the private member variables, as you define operator+ as a member function.

Edit: just to add working code

#include <iostream>

class Box
{
private:
double length;
double breadth; // ?? do you mean "width"?
double height;

public:
Box() {}
Box(const double l, const double b, const double h)
: length(l)
, breadth(b)
, height(h)
{}

// I don't know why the members are private? But you need access to check for a cube.
double getLength() const { return length; }
double getBreadth() const { return breadth; }
double getHeight() const { return height; }

double getVolume() const
{
return length * breadth * height;
}

// Overload + operator to add two Box objects.
Box operator+(const Box& b)
{
return Box (
length + b.length,
breadth + b.breadth,
height + b.height);
}
};

class Cube : public Box
{
public:
Cube(const double size = 0)
:Box(size, size, size)
{}

Cube(const Box& b)
: Cube(b.getLength())
{
if ((b.getLength() != b.getBreadth()) || (b.getLength() != b.getHeight()))
throw std::invalid_argument("Box is not a Cube!");
}
};

// Main function for the program
int main() {
Cube C1(5), C2(10), C3;
C3 = (C1 + C2);
std::cout << "Volume of C3 : " << C3.getVolume() << std::endl;
int temp;
std::cin >> temp;
return 0;
}

Is the assignment operator inherited or not?

The generated assignment is "all the base assignments, in order of inheritance declaration", so your generated assignment is essentially

D& operator=(const D& d)
{
B::operator=(d);
return *this;
}

If you were to derive from both B and C - in that order; class D: B, C - it would be equivalent to

D& operator=(const D& d)
{
B::operator=(d);
C::operator=(d);
return *this;
}

That is, the assignment is not inherited, but it's used.



Related Topics



Leave a reply



Submit