2

Let's say that I have two classes

Base manages some memory. It has working move, swap, assignment and destructor. Derived does not add anything new that need need to be managed (no new memory allocations).

class Base
{
public:
    Base();
    Base(const Base& other);
    friend void swap(Base& a, Base& b);
    Base(Base&& other);

protected:
    int** some2Darray;
    int w, h;
};

class Derived : public Base
{
public:
    Derived();
    //...?
};

Do I need to implement all those functions in derived class for it to be good? How to reuse those functions from base class? I don't need to manage any more memory in this class.

How those function would look if I added member to Derived class? Should I totally rewrite all those functions or is there some way to use for example "copy" base class and just copy that one added member additionally in copy constructor?

Cœur
  • 37,241
  • 25
  • 195
  • 267
Hooch
  • 28,817
  • 29
  • 102
  • 161
  • Does it have to be inheritance, would composition not work? If you just want `Derived` to have access to the resource managed by `Base`, you can simply add a `Base` member to `Derived`. –  Dec 15 '13 at 12:17
  • This looks like a classic [XY question](http://www.perlmonks.org/?node_id=542341) – StoryTeller - Unslander Monica Dec 15 '13 at 12:20

3 Answers3

7

You can inherit (edit: yeah, well this is not true inheritance, maybe this shall be noted explicitly) constructors since c++11. Via

class Derived : public Base
{
public:
    Derived();
    using Base::Base; // <-- this will import constructors
};

But this will not take care of any extras!

However, you do not need to copy code. You can just call parent functions.

E.g:

class Derived : public Base
{
   int extra;
public:
   Derived() : Base(), extra(42){};
   Derived(const Derived& other) : Base(other) {extra = other.extra;};
   void copy(const Derived& other);
   friend void swap(Derived& a, Derived& b);
};

void Derived::copy(const Derived& other){
   Base::copy(other);
   extra = other.extra;
}

Also don't forget about virtual destructor.

EDIT: For swap I would just cast derived instances to their bases to make compiler use the swap defined for parent type. Then swap extra stuff.

void swap(Derived& a, Derived& b){
    swap(static_cast<Base&>(a), static_cast<Base&>(b));
    swap(a.extra, b.extra);
}
luk32
  • 15,812
  • 38
  • 62
  • Thanks. That what I'm looking for. One more thing. If I dont' have any extra member in derived do I have to declare copy constructor? Or can I trust compiler to call one from base class? – Hooch Dec 15 '13 at 12:37
  • One more question and I'll accept it. What about swap function in derived class? I have swap functions as friend functions. How to reuse swap function from base? – Hooch Dec 15 '13 at 18:49
  • @Hooch Ok. I misunderstood at the begining, so I had to delete my comment. Again firstly sorry for not responding to the 1st question, but Matthieu's answer covered in in great detail before I got to it. I edited the answer. I think this should work. – luk32 Dec 15 '13 at 19:30
2

First of all: constructors, assignment operators and destructors are not inherited (*). Instead, they may, in some circumstances, be synthesized automatically for you by the compiler.

So, when do you need to write them ? Only when the default generated version does not correspond to your needs:

  • the accessibility is not what you wish (it's always public)
  • the method should be deleted
  • the default behavior is incorrect (shallow copy, for example)
  • the compiler cannot synthesize the method for you

Regarding the latter two points:

  • the Rule of Three states that if you write any one of the Copy Constructor, Copy Assignment Operator or Destructor; you should provide the other two as well
  • in C++11, if you write any of those 3 special methods, then the Move Constructor and Move Assignment Operator are not synthesized automatically
  • in C++11, if you write either a Move Constructor or Move Assignment Operator, then none of those 3 special methods is synthesized automatically either

(*) The C++11 feature called inheriting constructors is ill-named, it is more delegating than inheriting.


That being said, if Derived does not have any tricky attribute, then you can probably avoid writing those members. If you still wish to write them (to avoid inlining for example), you should be able to use the = default syntax:

// Derived.h
class Derived: public Base {
public:
    Derived(Derived const&) = default;
    Derived& operator(Derived const&);
};

// Derived.cpp
Derived& Derived::operator=(Derived const&) = default;
Matthieu M.
  • 287,565
  • 48
  • 449
  • 722
  • So then Derived(Derived const&) = default; will call copy constructor from Base? – Hooch Dec 15 '13 at 12:39
  • @Hooch: yes, as well as the copy constructor of each and every other base and attribute of `Derived` in the order of their declaration. – Matthieu M. Dec 15 '13 at 12:44
1

I'm not sure about the move operator, but you don't have to implement copy ctor, destructor and copy operator as the standard functions will automatically call the corresponding functions from all base classes.

EDIT: see also How to use base class's constructors and assignment operator in C++?

Community
  • 1
  • 1
MikeMB
  • 20,029
  • 9
  • 57
  • 102