About uncopyable class (on book:Effective C++)

See the following code:

#include<iostream>
using namespace std;
class Uncopyable
{
protected:
    Uncopyable(){cout<<"hehe\n";}
    ~Uncopyable(){}
private:
    Uncopyable(const Uncopyable &rhs){cout<<"oooops\n";};
    Uncopyable& operator=(const Uncopyable &rhs);
};

class Dog : private Uncopyable
{
    string name;
    int value;
public:

    Dog(const string &s, const int &v):name(s), value(v){}
public:
    //Dog(const Dog &rhs){};             //here is the question!
};

int main()
{
    Dog a("a", 9);
    Dog b(a);
}

If I comment out that line, g++ will complaint "Uncopyable::Uncopyable(const Uncopyable&) is private". I think that mean the default copy ctor of derived class created by g++ called the base class' copy ctor.

If I make available of that line, every thing is ok. It out put

hehe
hehe

I think this mean the default copy ctor of derived class created by g++ called the base class' default ctor.
Am I right? If yes, why doesn't the default copy ctor derived class, in condition 2, call the base class' copy ctor? Why it behave so inconsistently?

thank you!

A copy constructor's not going to get called unless you copy it. Your Dog(const Dog &rhs) constructor does literally nothing -- it's not even going to copy Dog, and passes nothing into Uncopyable. Lacking any other information, the compiler uses the default.

Thanks, but I want a more precise answer...

More precise than what? There is not a lot more information to be had.

1) You have overloaded the = operator.
2) You don't assign to that class using the = operator anywhere.
3) Therefore, the = operator is not called.

Next,

1) You have overloaded the Dog() constructor. This means you get to choose what you pass into Uncopyable().
2) You don't pass anything into Uncopyable().
3) Therefore nothing gets passed into Uncopyable(). It uses the default constructor.

It's not going to assume what things it shouldn't and shouldn't take from a custom constructor. If you wanted it to use the other constructor, you'd have to tell it, something like so:

Dog(const Dog &rhs):Uncopyable(rhs) {}

You can ignore operator=, since I don't use it.

I mean, If I comment out that line copy ctor, g++ will generate one, and it tries to call Uncopyable(const Uncopyable &rhs){cout<<"oooops\n";}, and then of course fails due to private attribute.
If I reserve that line, g++ will not generate the default version of copy ctor, and my version tries to call Uncopyable(){cout<<"hehe\n";} and of course succeed.

I don't know why it behave so inconsistently. aka, Why don't both call Uncopyable(){cout<<"hehe\n";} or Uncopyable(const Uncopyable &rhs){cout<<"oooops\n";}(which I think is more reasonable)?

It's not inconsistent, you get what you ask for, nothing more, nothing less.

What did you pass into Uncopyable() there? Nothing -- absolutely nothing.

What did it pass into Uncopyable()? Nothing, absolutely nothing.

The default copy constructor isn't called by the Dog() class because you overloaded it. It does what you say, instead of the defaults. That's what overloading is for. If you want default behavior, either don't overload it, or call it yourself...

1 Like