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.
Answers were Sorted based on User's Feedback
Answer / kamna
class A;//forward decleration
class B
{
B();
public:
friend A;
}
class A:public virtual B
{
public:
A()
};
class C:public A
{
public:
C()
};
int main()
{
A a; // allowed
C c;//not allowed
return 0;
}
Is This Answer Correct ? | 8 Yes | 1 No |
Answer / boriska
OK, here is the piece of code which illustrates the concept
=======================================================
class Base
{
private :
char _id;
~Base() {};
public :
Base(char id='0') : _id(id) {};
static Base* CreateBase(char id) { return new Base(id); }
static void DestroyBase(Base* ptr) { delete ptr; }
};
/**/
class Derived : public Base
{
public :
Derived(char id='1') : Base(id) {};
~Derived() {};
};
/**/
int main(int argc, char** argv)
{
Base* pb = Base::CreateBase('B');
Base::DestroyBase(pb);
return 0;
}
=================================================
I should have added that since Base class declares
destructor private, it cannot be instantiated directly
either, but I though it is kinda self-evident. My apologies
- just typed quick answer, describing a concept.
So here you go : you need static create/destroy functions,
declared within the scope of the Base class (or friend
functions, declared globally).
Now the major point : no matter how you try, declaration of
class Derived will not pass compilation - unless you define
similar create/destroy methods for class Derived within
Base class scope - which you, as a designer, choose not to
do. Here is the compiler error, produced at line with "void
Derived::~Derived()" declaration (compiled in .NET) :
==========================================
1>.\Test.cpp(46) : error C2248: 'Base::~Base' : cannot
access private member declared in class 'Base'
1> .\Test.cpp(35) : see declaration of 'Base::~Base'
1> .\Test.cpp(32) : see declaration of 'Base'
======================================
If you still in doubt - try this piece of code for yourself.
If you comment out declaration of class Derived, code
compiles just fine.
Now a bit of personal advise for Mms Zubeir : in the future,
before calling other's people opinion a "junk", try to give
it a little thought...and by extension, benefit of doubt to
your own self-assured opinion. This attitude may look good
on interview for some junior/mid-level position - for some
dumb hiring manager, grown on Scott Meyers/C++ in 21 day
type of books :-) But, it will not earn you much respect
amongst professionals. Arrogance is usually sure sign of
ignorance and lack of confidence...never convincing, and
rather good cause for laughter instead. Please remember that
next time before opening your mouth in attempt to discredit
other people's views.
Is This Answer Correct ? | 3 Yes | 0 No |
Answer / boriska
CORRECTION to my previous post : please strike out "unless
you define similar create/destroy methods for class Derived
within Base class scope". Does not change the major idea,
just implications - but not well thought over.
The correct way is to declare class Derived as a friend to
class Base - like :
class Base
{
friend class Derived;
...
}
then Derived will be able to access Base's private
destructor. But you don't want to let that happen - as I
said - if you want to prohibit any further derivation. But
if you want to make an exception for some predefined types
derived from Base, that is the way.
Cheers and apologies.
Is This Answer Correct ? | 3 Yes | 0 No |
Answer / boriska
Mms, thanks for arising my curiosity on the subject -
actually, there is very elegant solution to make class no
inheritable and allow it on stack. The idea is to virtually
inherit from base class with private destructor. Virtual
inheritance will force derived classes to call virtual base
destructor first, and it would be impossible because its is
private. Much better than solution I described, must admit.
Ok, here is the link with very good description :
http://www.codeguru.com/cpp/cpp/cpp_mfc/stl/article.php/c4143/
Is This Answer Correct ? | 2 Yes | 0 No |
Answer / mms zubeir
All the answers above are wrong. Guys, Don't provide some
junk answers! It may be misinterpretted by someone who has
less knowledge about the subject.
Is This Answer Correct ? | 0 Yes | 0 No |
Answer / mms zubeir
Thanks for your detailed answer. It's good to see you have
achieved the purpose partially by using static methods.
Still, we cannot create objects on the stack rather it
allows to create objects only on the heap. This is because,
we have to call the destructor using delete. You have
provided static methods to do that.
The compiler will not allow to create stack objects since
it cannot be able to invoke the destructor when unwinding
stack.
I do not have an idea how to fulfill this requirement.
Anyway, you have rolled out the solution to some extent.
Thanks.
Is This Answer Correct ? | 0 Yes | 0 No |
Answer / 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 |
Answer / mms zubeir
Thanks for the detailed answer. It's really pleased me the
way your answer is. Initially I wrote 'partial
implementation' since I couldn't get the details out of
your first answer. I am looking at the codeguru solution.
Thanks once again.
Is This Answer Correct ? | 0 Yes | 0 No |
Answer / abhishek
i think we r discussing c++ not java MR S.v.vignesh.....
!!
Is This Answer Correct ? | 0 Yes | 0 No |
Answer / geetha
sorry pa i can't understand any answer from ur points,i
think u r just copy down the answers from the book.you have
any other idea means plz tell me .i am very confused
Is This Answer Correct ? | 0 Yes | 0 No |
Describe friend function & its advantages.
What is an action class?
Badboy is defined who has ALL the following properties: 1. Does not have a girlfriend and is not married. 2. He is not more than 23 years old. 3. The middle name should be "Singh" 4. The last name should have more than 4 characters. 5. The character 'a' should appear in the last name at least two times. 6. The name of one of his brothers should be "Ram" Write a method: boolean isBadBoy(boolean hasGirlFriend , boolean isMarried, int age , String middleName , String lastName , String[] brotherName); isHaveGirlFriend is true if the person has a girlfriend isMarried is true if the person is married age is the age of the person middleName is the middle name of the person lastName is the last name of the person brotherName is the array of the names of his brothers
I want explanation for this assignment: how to connect mysql database using c/c++,please explain this detailly?
What is difference between shallow copy and deep copy? Which is default?
Which one is better- macro or function?
How do you generate a random number in c++?
how to swap two numbers with out using temp variable
12 Answers Global eProcure, TCS,
Perform addition, multiplication, subtraction of 2-D array using Operator Overloading.
What are the benefits of operator overloading?
Write a C++ program to sort digits of all the 4 digit number and display the sorted 4 digit number
Do you need a main function in c++?