Friday, July 22, 2005

One lil' problem

I borrowed this idea from this friend of mine. Instead of me blurting out some C++ funda, this time I'll pose it as a question. Will post the solution on this very same post on monday.

How to simulate a 'final' class of Java in C++? A final class is one which cannot be extended by inheritance. There's no built-in language mechanism in C++ to disallow inheritance. So, the solution would involve using some other C++ constructs to make a class behave like a final class.

I have one solution for this. There might be other solutions too. If you arrive at a solution, please mail the solution to me at srinivasa.s@gmail.com

My solution would follow here...

template < typename T >
class MakeFinal
{
  private:
    // declare/define all ctors & = op here

  public:
    // nothing needed actually

  // This is the line that makes this solution!
  friend T;
};

Now - for any class that you'd want to make final, just inherit from the above class virtually!

class MyClass : virtual public MakeFinal< MyClass >
{
  // ...
};

Inheritance from MyClass would not work, because MakeFinal has only private ctors. MyClass is a friend of MakeFinal, so it can call the private ctors of MakeFinal. But since the class inheriting from MyClass is not a friend of MakeFinal and since MyClass inherits virtually from MakeFinal, the inheriting class cannot call MakeFinal's ctors.

Hope this was a good solution... Do let me know if I missed anything.

7 comments:

  1. solution from subzero

    Would this work?

    class A
    {
    public:
    /*
    Use this method to create objects of type A
    */
    static A* getA()
    {
    return new A;
    }

    private:
    A(){ }
    // other ctors if needed
    };

    class B: public A
    // can't inherit from because
    // A's default constructor is
    // hidden
    {
    };

    ReplyDelete
  2. Yours is a 2 tier soln and more closer to what is offered in java.
    (i.e, irrespective of whats there in the class the final directive makes it non-inheritable..) where as in sub0's soln the ctor of the class has to be private.
    Neat one :)

    ReplyDelete
  3. Naren -> Firstly, Srinivas' solution is definitely cleaner than mine. But if you really are interested in proximity to Java, then even in the case of Srinivas' solution, your *final* class still has to inherit (virtually) from the parent class, in order to become *final* which is not quite the way it happens in Java anyway.

    And also, since Java comes with a home-grown compiler, how difficult would it be to translate a
    C c = new C();
    into a
    C *c = C::getObject();
    ;-))

    ReplyDelete
  4. sub0 - you're right. and the only drawback with the first solution was that every class that had to be made final had to have private ctors and other helper public functions. this is considered as an interface problem.

    ReplyDelete
  5. Guys, I hope everyone got why virtual inheritance is important here!

    ReplyDelete
  6. ummm... why the need for virtual inheritance out here?

    ReplyDelete
  7. sanjiv - consider what would've happened with normal inheritance. Say you inherit from "MyClass". While the creation of an object of this inherited class, its constructor would invoke MyClass constructor which inturn would invoke the constructor of MakeFinal. This would work because, MyClass is a friend of MakeFinal. What virtual inheritance does is - it makes the initialization of the most base class, the responsibility of the class of the object being instantiated. So, now your inherited class would have to invoke MakeFinal's constructor. This would fail because, the constructor is private and your class is not a friend of MakeFinal.

    This is exactly how virtual inheritance solves the problem in diamond inheritance. In diamond inheritance, its the responsibility of 2 classes to initialize the sole base class which would lead to double initialization. What virtual inheritance does is that the most derived class initializes the most base class.

    Hope it was clear.

    ReplyDelete

What I want to say is: