tags:

views:

169

answers:

3

I found this code here

class Usable;

class Usable_lock {
    friend class Usable;
private:
    Usable_lock() {}
    Usable_lock(const Usable_lock&) {}
};

class Usable : public virtual Usable_lock {
    // ...
public:
    Usable();
    Usable(char*);
    // ...
};

Usable a;

class DD : public Usable { };

DD dd;  // error: DD::DD() cannot access
        // Usable_lock::Usable_lock(): private  member

Could anybody explain me this code?

EDIT: Also another question i have is what is a virtual derivation and when is it needed?

+1  A: 

class Usable_lock's Constructor is declared under Private So it is not accessible Outside

Usable_lock class 

when you make object of

 DD dd;

It will call constructor of Usable and Usable_Lock both (because DD derived from Usable and Usable Derived from Usable_lock)

and thus it can't access Usable_Lock's Constructor.. and it will give you error

mihirpmehta
However `class Usable` is a friend and so should be able to access it. `DD` should not be accessing `Usable_lock`, it's `Usable` s job (?).
Pasi Savolainen
@Pasi: `Usable_lock` is a `virtual` base, so derived classes need to be able to access one of its constructors. Unfortunately, mihirpmehta's answer fails to mention that.
sbi
@sbi yes very true... i failed to mention that... ;(
mihirpmehta
+1  A: 

There are two points here:

1) Why Usable instance can be created, though it involves private Usable_lock constructor? Because Usable is friend of Usable_lock.

2) Why Usable-derived instance cannot be created? Because it involves private Usable_lock constructor.

Alex Farber
Hint - it's about `virtual` derivation.
Nikolai N Fetissov
+5  A: 

It's a property of virtual derivation.

The idea of virtual derivation is to solve the "Dreaded Diamond Pattern":

struct Base {};

struct D1: Base {};
struct D2: Base {};

struct TopDiamond: D1, D2 {};

The problem here is that TopDiamond has 2 instance of Base here.

To solve this problem, very peculiar "MultiInheritance", C++ uses the virtual keyword and what is thus called "virtual inheritance".

If we change the way D1 and D2 are defined such that:

struct D1: virtual Base {};
struct D2: virtual Base {};

Then there will only be one instance of Base within TopDiamond: the job of actually instantiating it is left to the top-constructor (here TopDiamond).

Thus, the little trick you have shown is simply explained here:

  • because Usable derives virtually from Usable_lock, it's up to its derived class to instantiate the Usable_lock part of the object
  • because Usable_lock constructor is private, only itself and Usable (friend) can access the constructor

It's clever, I had never thought of that. I wonder what the cost of virtual inheritance is here (extra memory / speed overhead) ?

Matthieu M.
Yup, this sums it up quite nicely. I'd spend a little less time on explaining what virtual inheritance is generally good for, but then I was to lazy to write an answer myself. `:)` +1 from me.
sbi