Home > Blockchain >  Calling copy and assignment operators from base class to create inherited class instances in C
Calling copy and assignment operators from base class to create inherited class instances in C

Time:07-14

I have te following classes (e.g.) :

class A {

   public:
   A(void) : i(0) {}
   A(int val) : i(val) {} 
   A(const A& other) : i(other.i) {}
   A& operator=(const A& other) {
       i = other.i;
       return *this;
   }

   int i;
};

class B : public A {

   public:
   B(void) : A(), j(0) {};
   B(const B& other) : A(other), j(other.j) {}
   B(int i, int j) : A(other.i), j(other.j) {}
   B& operator=(const B& other) {
      A::operator=(other);
      j = other.j;
      return *this;
   }
   
   int j;
};

My question is, given the operator= overload and copy constructor in B, if I wanted to be able to create instances of B out of an already initialized instance of A, or to assign existing instances of A to existing instances of B, would it be necessary to define another copy constructor on B and operator= with the following signature ?:

B(const A& other);
B& operator=(const A& other);

The goal would be to be able to instantiate/assign derived class instances only with the Base class information.
PS : I am working in C 98 and unable to use any newer standard.

CodePudding user response:

The goal would be to be able to instantiate/assign derived class instances only with the Base class information.

Your goal sounds fishy to me.

Normally in practice, you have two distinct scenarios:

  • data objects (requiring no inheritance hierarchy)
  • behavior objects (implementing the same interface, through inheritance).

Data objects (since they have no common base class) implement instantiation and assignment (copy constructors and assignment operators).

Behavior objects (objects within class hierarchies) cannot implement assignment from base class objects in a generic way (what will you do with member variables that exist in the derived class but not in the base class? give them a default value? leave them unchanged?).

That said, you should use a different API than copy constructor and assignment in order to avoid confusion and implicit casts.

That is, if you have both:

B& operator=(const B&);
B& operator=(const A&);

then this is ambiguous when the code assigns from a B instance (as the compiler could call either of them).

You could add a B::copy_common_values(const A&);. This would make it more explicit as well.

In case you are trying to solve an x-y problem, also look up prototype design pattern.

CodePudding user response:

Yes, you would have to define something like that.

B(const A& other);

This would allow constructing B out of A. This would also allow assigning A to B by way of implicitly converting A to B and then assigning. So that alone should suffice. But you get an extra copy.

B& operator=(const A& other);

This makes assigning A to B more efficient since you avoid the extra copy of the temporary B. This should also allow assigning things that can be implicitly converted to A like:

B b = 1;

If you don't want that you might have to add some explicit. Did C 98 have explicit? That is so last millenium.

Note: In modern C this would be more efficient because of copy elision and because you could use move semantic and perfect forwarding references.

  • Related