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

Does std endl flush?

613


What are punctuators in c++?

656


What is the real purpose of class – to export data?

618


What is #include math h in c++?

574


Explain the auto storage classes in c++.

605






Can I learn c++ in a week?

583


Is c++ pass by reference or value?

575


How would you obtain segment and offset addresses from a far address of a memory location?

622


What is a stack? How it can be implemented?

700


What does 7/9*9 equal ? a) 1 b) 0.08642 c) 0

585


What are signs of manipulation?

597


What is c++ runtime?

659


What is polymorphism and its type in c++?

594


What is long in c++?

740


Do you need a main function in c++?

561