How would you stop a class from class from being derived or
inherited?The constructer should not be Private,as object
instantiation should be allowed.

Answer Posted / boriska

Mms,
- hmmmm, I am not sure I understand why do you think static
factory methods have anything to do with prohibitng
derivation. Please note, that compiler produces error *at
derived class declaration* and it will still produce the
same error even if you commnet out calls to static
creational methods form main().

If I am not mistaken, you are confusing here two completely
unrelated aspects - outer caller's convenience when
instantiating base class and possibility of deriving objects
from it. Static nature of creational methods is merely a
quick and well known way to provide creation/cleanup calls
within the scope of base class - a quick hack, if you will.

It is perfectly possible to deal completely without
class-level static calls and achieve the same purpose -
prohibiting derivation. You may create instances of base
class form another stack-allocated object variable - e.g.
from smart pointer-type handle, placed at the stack in
caller's code (which is by the way, quite useful paradigm as
far as C/C++ memory management is concerned).

E.g., you can use auto_ptr from STL (which is poor choice)
or, better, shared_ptr from BOOST, or develop your own
ref-counted pointer - as I did here, just for the sake of
example.

Here is a quick sample code (again just a way to illustrate
the idea). In the code, Master maintains ownership of object
and implements refcounting, HandlePtr is a stack variable to
provide access to object. Again, I typed it just to
illustrate concept above - just a prototype, not for
detailed discussion. Memory management is a separate topic
from prohibiting derivation.

=======================================================
template <class T> class Master
{
private:
unsigned _refCnt;
T* _ptr;

// proihibit copy & assignment
Master(const Master& rhs) : _refCnt(0), _ptr(NULL) {}
void operator =(const Master& rhs) {}

public:
// dflt ctor
// null0new1 = 0 : _ptr = NULL
// null0new1 = 1 : _ ptr = new object (assume it has dflt ctor)
Master(int null0new1=1) : _refCnt(1) { _ptr = null0new1 ?
new T : NULL; }

// init ctor : takes ownership of pointee
Master(T* ptr) : _refCnt(1), _ptr(ptr) {}

// dtor
~Master() { delete _ptr; }

// ref counting
void grab() { ++_refCnt; }
void release() { if (--_refCnt == 0) delete this; }

T* raw_ptr() { return _ptr;}

T* checked_ptr()
{
if (_ptr == NULL) throw "Dereferencing NULL pointer";
return _ptr;
}
};

template <class T> class HandlePtr
{
private :
Master<T>& _master;

public :
// dflt ctor
// HandlePtr() - create new object
// HandlePtr(0) - create NULL ptr
HandlePtr(int null0new1=1) : _master(*(new
Master<T>(null0new1))) {}

// init ctor : grabs ownership of pointee
HandlePtr(T* ptr) : _master(*(new Master<T>(ptr))) {}

// dtor
~HandlePtr() { _master.release(); }

// copy
HandlePtr(const HandlePtr<T>& rhs) : _master(rhs._master) {
_master.grab(); }

// assignment
HandlePtr& operator =(const HandlePtr<T>& rhs)
{
if (this != rhs)
{
_master.release();
_master = rhs._master;
_master.grab()
}
}

//member selector and dereference
T* operator ->() { return _master.checked_ptr(); }
T& operator *() { return *_master.checked_ptr(); }
};


class Base
{
//uncomment below to allow derivation for Derived :
//friend class Derived;

friend class Master<Base>;
private :
char _id;
~Base() {};
public :
Base(char id='0') : _id(id) {};
char id() { return _id; }
virtual void print() { cout << "Base : " << id() << endl;}
};

/**
class Derived : public Base
{
friend class Master<Derived>;
public :
Derived(char id='1') : Base(id) {};
~Derived() {};
virtual void print() { cout << "Derived : " << id() << endl;}

};
/**/

int main(int argc, char** argv)
{
//HandlePtr<Base> base;
//base->print();
/*
HandlePtr<Derived> derived;
derived->print();
*/
return 0;
}
================================================

As you can see - no static methods at all. Yet again, you
see the same thing : compiler will produce error at Derived
declaration, even if main() is dummy. So Derived declaration
will not fly. You have to either comment out Derived
declaration or make it a friend to Base - as I described in
previous post.

I don't see why you think the purpose is achieved, as you
said, "partially" :-) Now, if you still feel uncomfortable
about using Base class (from this example) via intermediate
stack-based handle - rather than allocating Base instances
directly on the stack - you probably should think why in the
world does it make such a difference for you. Unless you
have a special affinity for "dot" member selector (which
cannot be overloaded) as opposed to "arrow" member selector,
used by smart pointers - I don't see what's the big freaking
difference between instantiating variables on the stack or
in the heap. Look at Java, look at C# - for exception of
value types in C#, objects are usually allocated on the
heap, and stack variables are mere references.

And if you still really really want to find solution how to
prohibit further derivation for value types which are
typically allocated on the stack (which seems to be your
major concern) - chances are, your design is really flawed.
Stack-based value types are usually not a good candidates
fro derivation in a good design anyway.

Please, think it over before typing quick reply about
"partial implementation", or "smart pointer semantics" or
whatever else being a limitation and "partial" solution etc.
It could be, actually, quite misleading for beginners :-)

Cheers

Is This Answer Correct ?    0 Yes 0 No



Post New Answer       View All Answers


Please Help Members By Posting Answers For Below Questions

If a function doesn’t return a value, how do you declare the function?

705


How the memory management in vectors are being done. What happens when the heap memory is full, and how do you handle it ?

1932


How do you clear a buffer in c++?

632


How to implement is-a and has-a class relationships?

665


Explain the purpose of the keyword volatile.

727






What is c++ redistributable?

717


What is the use of 'using' declaration in c++?

720


What is polymorphism in c++? Explain with an example?

689


What is the need of a destructor?

742


What is the difference between a reference and a pointer?

681


In the derived class, which data member of the base class are visible?

739


List the features of oops in c++?

662


Can I learn c++ as my first language?

741


What is microsoft c++ redistributable 2013?

665


What is object in c++ wikipedia?

645