Skip to main content
gamedev.net
🔒 Locked

Coding the Uncreatable

Started by gimp Dec 12, 2001 at 6:46 PM 18 replies 1k views
Original Post
gimp
gimp
I''d like to code a class CNonCreatable. So, that when I create a new class, say CPartition, which shouldn''t be used for anything but deriving from. How can I do that cleanly? Chris Brodie http:\\fourth.flipcode.com
Chris Brodie
jenova
jenova
in "java" make the class "abstract".
in "c++" just have one method that is abstract:

i.e.

class CNonCreatable {
public:
virtual SomeMethod(void) = 0;
};

// the "= 0;" makes the method abstract and thus cannot create an instance of this class. not sure if you need the virtual.

To the vast majority of mankind, nothing is more agreeable than to escape the need for mental exertion... To most people, nothing is more troublesome than the effort of thinking.
To the vast majority of mankind, nothing is more agreeable than to escape the need for mental exertion... To most people, nothing is more troublesome than the effort of thinking.
Oluseyi
Oluseyi
It works. Those "=0" functions are called pure virtual methods (in C++), and you are not permitted to create instances of pure virtual classes (classes with one or more pure virtual methods).

[ GDNet Start Here | GDNet FAQ | MS RTFM | STL | Google ]
Thanks to Kylotan for the idea!
jenova
jenova
Oluseyi: that''s right, i just couldn''t remember the name even though i use it for my base class "Object" for everything else i do.

To the vast majority of mankind, nothing is more agreeable than to escape the need for mental exertion... To most people, nothing is more troublesome than the effort of thinking.
To the vast majority of mankind, nothing is more agreeable than to escape the need for mental exertion... To most people, nothing is more troublesome than the effort of thinking.
Floppy
Floppy
quote:
Original post by Oluseyi
It works. Those "=0" functions are called pure virtual methods (in C++), and you are not permitted to create instances of pure virtual classes (classes with one or more pure virtual methods).


..., and you have to define in your derived class the method defined as pure virtual (int doIt()=0; ) in your super class.


Edited by - Floppy on December 12, 2001 8:08:23 PM
Oluseyi
Oluseyi
quote:
Original post by Floppy
..., and you have to define in your derived class the method defined as pure virtual (int doIt()=0; ) in your super class.

Yeah, thanks for that.

[ GDNet Start Here | GDNet FAQ | MS RTFM | STL | Google ]
Thanks to Kylotan for the idea!
xyzzy00
xyzzy00
Alternatively, you can just make your constructor protected.

xyzzy
Oluseyi
Oluseyi
quote:
Original post by xyzzy00
Alternatively, you can just make your constructor protected.


That''s quite close to the Singleton pattern, where the private/protected constructor is complemented by a Create() method. If your Create() method indiscriminately returns valid objects, then making the constructor protected is a waste.

However, while a protected constructor will not allow objects of that class to be created, it doesn''t ensure that an instance never exists. That''s specifically what pure virtual functions are for; why not use them?

*shrugs*

No big deal I guess - another preference.

[ GDNet Start Here | GDNet FAQ | MS RTFM | STL | Google ]
Thanks to Kylotan for the idea!
DigitalDelusion
DigitalDelusion
And you don''t even have to make every derived class implement the dummy function.

this is valid:

class CNonCreate
{
protected:
virtual void dummyfunc() = 0;
};

void CNonCreate::dummyfunc()
{}

class CCreate : public CNonCreate
{
using CNonCreate::dummyfunc;
public:
};

this way you don''t have to implement the dummyfunc in the derived classes
HardDrop - hard link shell extension."Tread softly because you tread on my dreams" - Yeats
null_pointer
null_pointer
quote:
Original post by Oluseyi

That's quite close to the Singleton pattern, where the private/protected constructor is complemented by a Create() method. If your Create() method indiscriminately returns valid objects, then making the constructor protected is a waste.



Why bother with a create member function?

#include <stdexcept>

class myclass
{
public:
myclass() { if( error_condition ) throw std::exception(); }
};



quote:
Original post by DigitalDelusion

...this way you don't have to implement the dummyfunc in the derived classes



This is merely a convoluted way of expressing something that can be more clearly expressed using a protected constructor. That's why we have protected constructors.

BTW, I thought that a pure virtual function is a pure virtual function, even if it has an implementation. IIRC, the language standard says that should a pure virtual function call occur, the program terminates on an error. (I forget exactly which handler it uses.) Can anybody verify this?


gimp: If you can make use of the pure virtual functions to specify the interface of the derived classes, then obviously pure virtual functions are the way to go. Otherwise, use the protected constructor.

- null_pointer

Edited by - null_pointer on December 13, 2001 9:16:10 AM
Beer Hunter
Beer Hunter
quote:
Original post by Anonymous Poster
In Delphi you would just say:
(snip)
Not that this would be much help if you are using C++, but it just goes to show that

Delphi Rules!!


The worst part is that the people above you already explained how to do it in c++. You should always read the posts in a topic before posting - you can save yourself a lot of embarassment.
Stoffel
Stoffel
quote:
Original post by null_pointer
BTW, I thought that a pure virtual function is a pure virtual function, even if it has an implementation. IIRC, the language standard says that should a pure virtual function call occur, the program terminates on an error. (I forget exactly which handler it uses.) Can anybody verify this?


You are partially correct. Even if you define a function body for a pure-virtual function in the base class, derived classes must override it or they will also be abstract. Not implementing the override and trying to create an object of the derived class will not compile, so it is in fact a compile-time error, not a run-time error. And we all like compile-time errors better than run-time errors.

So what's the point of defining a pure virtual function? It allows derived classes to call the base-class implementation explicitly in their override (or wherever they need to). Personally, I think this is obfuscating and would not espouse the practice, but it is legal.


Edited by - Stoffel on December 13, 2001 5:37:06 PM
gimp
gimp
Thanks all.

As it was my intention initially just to protect a certain class from being created I can solve this problem by just leaving a virtual function pure.

More generically I was curious to see if there was a generic solution that could be wrapped up. I sort of got the idea from the Boost library which has a ''CNonCopyable'' type class you can derive from. My idea was to have a similar clas that prevented direct use of a class. The problem I had was that if I created a generic pure virtual function that I''d have to implement it in the derived class.(As someone else eluded to above).

Protected constructors sounds interesting. Does that place any requirements on a derived class however? For example would a derived class need to reimplement a public constructor, or would the built in one be sufficient?

Many thanks to all the replies



Chris Brodie
http:\\fourth.flipcode.com
Chris Brodie
Shannon Barber
Shannon Barber
If you have no other virtual funtions in the base class the protected constructor would be preferable; adding virtual functions adds 4 bytes to the object size...

  
class CHackMister
{
public:
CHackMister(DWORD dwMagicNumber=0)
{
//Do not instance this class!

_ASSERT(dwMagicNumber==0x1234abcd);
}

};

Have the dervied classes explicitly call the base constructor with the magic number

Magmai Kai Holmlor

"Oh, like you''ve never written buggy code" - Lee

"What I see is a system that _could do anything - but currently does nothing !" - Anonymous CEO
The trade-off between price and quality does not exist in Japan. Rather, the idea that high quality brings on cost reduction is widely accepted.-- Tajima & Matsubara
Shannon Barber
Shannon Barber
Actually, isn''t convention to prefix such a base class with a leading underscore to indicate that it''s a ''private'' implementation class (keep your stinking hands off)?

Magmai Kai Holmlor

"Oh, like you''ve never written buggy code" - Lee

"What I see is a system that _could do anything - but currently does nothing !" - Anonymous CEO
The trade-off between price and quality does not exist in Japan. Rather, the idea that high quality brings on cost reduction is widely accepted.-- Tajima & Matsubara
null_pointer
null_pointer
If so then it is a bad convention. Names with leading underscores are reserved for use by the C++ implementation and should not be used by other programmers, because of the possibility of conflict. Use a trailing underscore, or simply drop the convention altogether.

- null_pointer


Edited by - null_pointer on December 15, 2001 12:27:10 PM

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.