Say I have a super class called VObject(). I want this class to have a static method called Alloc() and I want allow to do an allocation of the class and return a pointer. Something like this:

//---------------------------------------------------------------------------

class VObject{
public:

static VObject* Alloc(){
VObject *Result = new VObject();
return(Result);
}

};

//---------------------------------------------------------------------------

class MyObject : public VObject{

};

//---------------------------------------------------------------------------

void __fastcall TForm1::FormCreate(TObject *Sender)
{
VObject *Object = VObject::Alloc();
MyObject *Value = MyObject::Alloc(); /* Error here */

}

//---------------------------------------------------------------------------


The last line throws an error because VObject's Alloc() method allocated objects of type VObject(). How can I allow the VObject() super class to hide the Alloc() method inside itself without needing any of the sub classes to have the Alloc() method? So somehow make the MyObject object to inherit the Alloc() method but let it return an object of type MyObject() without needing to rewrite that method.
Posted on 2009-05-20 19:42:47 by XCHG
Okay I found my solution:

class VObject{

public:

unsigned int Value;

unsigned int RetainCount;

virtual void Dealloc(){
delete this;
}

template<class T>
static T *Alloc(T* t){
T* NewClass = new T();
NewClass->RetainCount = 1;
return(NewClass);
}

virtual bool Release(){
if (this->RetainCount > 0) {
this->RetainCount--;
if (this->RetainCount == 0) {
this->Dealloc();
}
return(true);
} else {
return(false);
}

}

template<class T>
T *Retain(T* t){
this->RetainCount++;
return(this);
}
};
Posted on 2009-05-22 04:52:37 by XCHG
Don't reinvent the wheel. Read about COM :)
Posted on 2009-05-22 21:08:04 by ti_mo_n
Hey,

I don't think COM is for other platforms but Microsoft hm? I am creating my own library of C++ files for making games and the VObject is the core object from which other classes will inherit. I am planning on using this code on other platforms like on Mac OS X so I don't know if I'm going to benefit from COM?
Posted on 2009-05-23 08:36:45 by XCHG
COM is usually mistaken (quite justifiably) for THE MS implementation, while actually it's just a method of creating objects, very similar to yours.
It would be easier for you to see what objects already are in COM specs (like streams, allocators, etc) and implement your own using existing ideas. The result will be easier to code (no planning required because you already see what you want), and easier to debug/test/play with because those familiar with COM will be able to help you with any problems. It's not really THE MS COM what I'm suggesting you, but 'the COM idea' of writing object oriented code.

So there are 2 main benefits of COM for you:
1) Known interface names. If you want a memory allocator, write your own IMalloc interface. If you want a universal stack, write IStack. Everyone will know how it works (or how it's supposed to work and if it doesn't you'll get more descriptive bugreport) and how to use it (you can focus on writing the code instead of documenting it).
2) COM mechanics allow easy extensions to the existing code. If an application uses a function from a DLL, then when this function is updated the app may stop working. This is not the case with COM. You can your libraries with new functions, update existing functions and every app written using some given version of your library will never stop working (as long as there is at least this version provided and -of course- as long as there are no bugs in the IUnknown interface of the library). So, for example, let's say I have a function called "add" in a library and this function takes 2 integers and returns an integer. In some next version of this library this "add" may take floats instead of integers. In the standard approach my app would crash/stop working correctly if I updated the library without recompiling the app. In the COM approach it will still function properly and NEW applications can use this new version of "add" (which takes floats instead of integers) as well as the old version (with integers). There may even be some newer version of "add" in the future and no existing code will stop functioning (as long as it's written properly). The "add" may even be deprecated/deleted in some new version and any extisting apps will still work properly without any changes to them.

COM is the only way I write ObjectOriented code and IMHO it's a great way of writing OO code. And I'm talking about the mechanics here, not THE MS COM. Or, in other words, I'm talking about the programming technique, not the COM implementation on Windows.

And that's what I'm suggesting you ^^

Here you can read about the benefits of COM.

The neatest fun starts if you want make UI elements (you said you wanted to make a game, right?). Having 3 versions of the same menu without conflicts, or 4 versions of 3D-model renderers is really nice. Upgrading COM code is as easy as copying new DLL to the game directory.

I haven't slept for like 30 hours so I hope this text isn't very chaotic/erratic/bugged and you get the idea ^^'
Posted on 2009-05-23 20:06:20 by ti_mo_n
I'm wondering what the use of your Alloc method is.
It's cheaper to issue a New() than it is to call the Alloc method (unless its an inline method) and either way it costs more to type the Alloc call than it does to type the New directive.
What do you have in mind here?
Posted on 2009-05-24 03:19:20 by Homer
Hm, to me it seems like a wrong idea to mess with manual reference counting this way - you're probably better off using something like boost::shared_ptr . (And you really should be setting refcount in your constructor rather than some custom alloc function that might not even be called).

What's with the "T* t" arguments to Alloc and Retain that aren't used?
Posted on 2009-05-24 16:43:31 by f0dder

Hm, to me it seems like a wrong idea to mess with manual reference counting this way - you're probably better off using something like boost::shared_ptr . (And you really should be setting refcount in your constructor rather than some custom alloc function that might not even be called).

What's with the "T* t" arguments to Alloc and Retain that aren't used?


I am not doing anything in the constructor because I want another method which is to be my actual constructor. I want all my objects to have one constructor which will eventually allow my new()  to work in the Alloc() static function. If they have a different constructor then Allloc() might not work because it assumes the object's constructor doesn't have any parameters. So I will define that as abstract = (0) in my base class and I will force all my other classes to have that. So basically the lifecycle of my objects will be like this:

1) Alloc (allocate memory for the object)
2) Init (initialize parameters, something like a constructor).
3) Retain, Release, Retain, Release as much as we want.
4) Dealloc.

I am using the function templates so I can do this:

class SObject : public VObject{
}

SObject *Bla = SObject::Alloc(Bla);

So this way SObject inherits its Alloc() from VObject() defined in my previous post and that will save me writing the Alloc() and Retain() functions for every class I create. If you have a better way of doing this, I will be glad to see that really. I don't like using Templates much.
Posted on 2009-05-25 09:47:02 by XCHG
As mentioned previously, for a lot of uses I'd simply depend on a shared_ptr to manage reference counting, and use clean-and-dependable RAII, which also fairs well in case of exceptions.

I'm also not sure what it is you really want to do wrt. the memory allocation thing. I'd prefer to overload operation new/delete per-class as necessary, which allows you to instantiate your objects on the stack as well as on the heap as wanted... and supports constructors.

Even with your scheme, I don't see the point of the alloc routine at all - the "retainCount = 1" should be done in the constructor instead, and derived classes should of course call it's superclass' constructor :)
Posted on 2009-05-25 14:35:49 by f0dder

As mentioned previously, for a lot of uses I'd simply depend on a shared_ptr to manage reference counting, and use clean-and-dependable RAII, which also fairs well in case of exceptions.

I'm also not sure what it is you really want to do wrt. the memory allocation thing. I'd prefer to overload operation new/delete per-class as necessary, which allows you to instantiate your objects on the stack as well as on the heap as wanted... and supports constructors.

Even with your scheme, I don't see the point of the alloc routine at all - the "retainCount = 1" should be done in the constructor instead, and derived classes should of course call it's superclass' constructor :)


Actually to be honest with you, I think a shared pointer should not modify the reference count since it is a shared pointer. If the instance is deallocated, since it is "shared", it has to be deallocated everywhere else. The way I will write a shared ptr in C++ and especially in Objective C is like this:


static MyClass *SharedInstance(){
 static MyClass *SharedInstanceVariable = NULL;
 if (SharedInstanceVariable == NULL){
   SharedInstanceVariable = new MyClass();
 }
 return(SharedInstanceVariable);
}


So basically keep the reference count to 1 when SharedInstanceVariable is allocated and don't change the reference count. That's how Objective C works and I think it makes sense.

The thing I want to do is this:

In Objective C, the head of the hierarchy is NSObject. Then you can inherit from it like this (h file):

#import <Foundation/Foundation.h>


@interface MyObject : NSObject {

}

@end


And this class, without any implementation, will be able to be allocated like this:

MyObject *Bla = [ init];


alloc is defined in NSObject and it will return an object of type (id) which is the wrapper for all classes. Then init will initialize the class. You can override the init function like this:


- (id) init {
 self = ;
 if (self != nil){
   /* Do your things here */
 }
 return(self);
}


So alloc is defined in NSObject and you don't have to override this for every object that inherits from it. The init() function as well.
Posted on 2009-05-26 04:42:46 by XCHG
A shared_ptr (of the boost kind, which was adopted by the C++ committee, will be included in C++0x and is already present in TR1) does handle reference counting properly, and is even threadsafe. The shared_ptr constructor (and copy constructor) increments the refcount, the destructor decrements it. If refcount==0 on decrement, the pointed-to object is deleted. Of course this does mean that to use shared_ptrs for reference counting you'd more or less need to always pass shared_ptrs around rather than your raw pointers.

I think you're trying to program in C++ but thinking in an Objective-C mindset? You "init" pretty much corresponds to a C++ constructor. And I still don't see your reason for the custom allocator; sure, right now it's used to set up reference counting, but that belongs in a constructor, and would only need to be done in the base class anyway.
Posted on 2009-05-26 05:00:33 by f0dder

A shared_ptr (of the boost kind, which was adopted by the C++ committee, will be included in C++0x and is already present in TR1) does handle reference counting properly, and is even threadsafe. The shared_ptr constructor (and copy constructor) increments the refcount, the destructor decrements it. If refcount==0 on decrement, the pointed-to object is deleted. Of course this does mean that to use shared_ptrs for reference counting you'd more or less need to always pass shared_ptrs around rather than your raw pointers.

I think you're trying to program in C++ but thinking in an Objective-C mindset? You "init" pretty much corresponds to a C++ constructor. And I still don't see your reason for the custom allocator; sure, right now it's used to set up reference counting, but that belongs in a constructor, and would only need to be done in the base class anyway.


Yeah I can say that I really am in an Objective-C mindset. I have been working with it for about 8 months now and it's amazingly clean and organized once you get used to it (which won't take long really). My problem is that I want to have New just allocate my objects. That's what it is supposed to do. I don't want it to Initialize my objects through the constructor and for this I have to have one simple constructor with no parameters so in my base class I can call that constructor without parameters and then allow the programmer to initialize the objects using a separate call.

So:

1) Allocate (don't initialize. These two are in my opinion two different things and I hate the fact that New mixes them together). (x1)
2) Initialize. (x1)
3) Retain. (xn)
4) Release. (xn)
5) Deallocate (x1)

Posted on 2009-05-26 05:13:56 by XCHG
I used to dislike initialization done in constructors (and especially constructor member initializers), but it does have a bunch of advantages - it's pretty consistent, helps a lot wrt. exception safety, and can help getting more optimal code with some compilers: your method would have class members getting default-initialized, and then afterwards being re-"initialized" by your Init() routine.

Doing it "your way" is of course possible, but it isn't "the C++ way" of doing things :)
Posted on 2009-05-26 05:21:06 by f0dder

I used to dislike initialization done in constructors (and especially constructor member initializers), but it does have a bunch of advantages - it's pretty consistent, helps a lot wrt. exception safety, and can help getting more optimal code with some compilers: your method would have class members getting default-initialized, and then afterwards being re-"initialized" by your Init() routine.

Doing it "your way" is of course possible, but it isn't "the C++ way" of doing things :)


You are right. I think I should start to accept that these two languages are structured differently. I wish C++ Builder (which is my main C++ IDE) could work with GNU Objective-C compiler. In XCode on the Mac I can write C, C++, Objective C in one file and have the compiler understand the whole thing. It's pretty intense.
Posted on 2009-05-26 05:25:55 by XCHG
Btw, another important rationale behind initializing objects via constructors is that you can ensure that an object will always be in a consistent state.

Putting multiple languages in one source module seems dirty, but linking several modules in different language can be useful. That'd let me use Obj-C exclusively for the GUI stuff and stick with C++ for the core parts of the app, should I ever need to do Mac programming :)
Posted on 2009-05-26 05:30:04 by f0dder

Btw, another important rationale behind initializing objects via constructors is that you can ensure that an object will always be in a consistent state.

Putting multiple languages in one source module seems dirty, but linking several modules in different language can be useful. That'd let me use Obj-C exclusively for the GUI stuff and stick with C++ for the core parts of the app, should I ever need to do Mac programming :)


Yeah mixing them could sometimes be dirty but sometimes really useful :P I probably will consider changing this Alloc() scheme that I had in mind then :-s
Posted on 2009-05-26 05:36:00 by XCHG
It's of course your choice, but all I can say is that languages are different. When I started writing C++, I did so with a C/ObjectivePascal mindset. I feel that my code has become cleaner after I've accepted more and more of "the C++ way". That has also brought me to realize that C++ isn't the perfect tool for every job, and that raw win32 API programming isn't the most joyful way of doing GUIs (although it is one of the LEAN_AND_MEANEST ways :)).
Posted on 2009-05-26 05:47:24 by f0dder

It's of course your choice, but all I can say is that languages are different. When I started writing C++, I did so with a C/ObjectivePascal mindset. I feel that my code has become cleaner after I've accepted more and more of "the C++ way". That has also brought me to realize that C++ isn't the perfect tool for every job, and that raw win32 API programming isn't the most joyful way of doing GUIs (although it is one of the LEAN_AND_MEANEST ways :)).


Yeah I totally agree with the fact that once you accept a programming language as it is, you will write cleaner code. I had the same problem with Delphi. I think it's best to understand the programming language and most/all its tools but sometimes it could be really hard to adjust to them since you might have experience in other programming languages more and essentially you will end up comparing how harsh the new language is compared to the one you are used to coding in for example. (sigh) Yeah I guess I have to go the C++ route instead. Oh well...
Posted on 2009-05-26 06:30:15 by XCHG
Well, at least going objpascal/objc -> C++ isn't that bad a step (although there are a damn lot of things you need to know about to write clean and efficient C++ code) - it's an "ideologically" smaller step than picking up, say, the Python mindset :)
Posted on 2009-05-26 06:37:59 by f0dder
Jumping from ObjectPascal to C++ would be difficult but from Delphi (especially with all the changes made to the language since Delphi 7) there is not much difference between these two worlds really. Templates are still missing from Delphi though :P
Posted on 2009-05-28 11:52:10 by XCHG