3

I'm confused about base classes and copy constructors.

Say I have a class

class A {
    public:
    A(int m) : m(m) { return; }
    virtual ~A() { return; }
    int m;
}

And a class that inherits this

class B : public A {
    public:
    B(int n, int m) : A(m), n(n) { return; }
    vitual ~B() { return; }
    int n;
}

When I copy class B, how do I ensure that the m value in class A is copied as well?

Tyler Jandreau
  • 4,245
  • 1
  • 22
  • 47
  • To be sure you can replace m and n with classes that have copy constructors. – Minimus Heximus Aug 02 '13 at 14:31
  • @LuchianGrigore Unrelated, but how do I know when to define my own copy constructor? – Tyler Jandreau Aug 02 '13 at 14:35
  • 2
    When the class manages a manual resource, usually when you have raw pointers and new. Members have their copy constructors called automatically by the default copy constructor. That is fine for a basic type such as int, or a class with a proper copy constructor such as std::string or std::vector. But regular pointers just copy their address - the resource they point to is not copied. Try to use smart containers and objects to avoid needing custom copy constructors as much as possible. – Neil Kirk Aug 02 '13 at 14:39
  • 1
    @TylerJandreau, see http://stackoverflow.com/questions/3278625/when-do-we-have-to-use-copy-constructors – Mark Ransom Aug 02 '13 at 14:40

4 Answers4

4

The default copy constructor will copy all of the member variables, no matter whether they reside in the base class or a derived class.

If you create your own copy constructor for class B you will need to copy the class A members yourself, or better yet use the copy constructor for class A in the initializer list.

class B : public A {
    public:
    // ...
    B(const B & b) : A(b), n(b.n) {}
    // ...
};
Mark Ransom
  • 299,747
  • 42
  • 398
  • 622
1

The base copy constructor will be called before the derived copy constructor automatically. It's the same as for a regular constructor. (More accurately, the base constructor is called by derived initialization list before derived constructor continues). In your case, the default copy constructors are sufficient.

Be careful, however, that you do not copy a B into an A (search object splicing).

Neil Kirk
  • 21,327
  • 9
  • 53
  • 91
0

This code is your code just copy constructors are added with a class:

#include <iostream>

using namespace std;

struct Int
{

    Int ()
    {
    }

    Int(const Int&)
    {
        cout<< "Int copied" "\n";
    }
};


class A
{
    Int m;
public:
    A(Int m) : m(m)
    {

    }
    virtual ~A()
    {

    }

};

class B : public A
{
    Int n;
public:
    B(Int n, Int m) : A(m), n(n)
    {

    }


    virtual ~B()
    {

    }

};

void f(B)
{

}

int main()
{
   Int m,n;
   B b(m,n);

   cout<< "\n" "start:" "\n";
   f(b);
   cout<< "end";

}

Ubuntu Qt Creator Output says both are copied.

One can think there's a hidden member with type B in A and this hidden member can be initialized or copied as a usual member as in the above program with:

B(Int n, Int m) : A(m), n(n)
Minimus Heximus
  • 2,683
  • 3
  • 25
  • 50
-1

You should not return from a constructor/destructor, not even void.

paper.plane
  • 1,201
  • 10
  • 17