can we override alloc and dealloc in objective C?
Asked Answered
E

2

6

I know that this is rarely required to override the alloc or dealloc methods,but if required is it possible in iPhone programming?

Egarton answered 29/9, 2011 at 11:28 Comment(0)
H
13

You can and indeed, you should (if using manual memory management) override dealloc to release any resources you hold (not forgetting to call [super dealloc] when finished). Overriding alloc is possible but, as you say, rarely needed.

Henricks answered 29/9, 2011 at 11:31 Comment(4)
A couple of notes: subclasses of NSObject should override allocWithZone: rather than alloc, and can't override dealloc in code that's compiled with ARC.Unsex
Correction: I should have said, "code compiled for ARC can't call [super dealloc]". It's still possible to override dealloc, but rarely useful.Unsex
overriding dealloc is still a good practice in case you need to unregister from notifications or remove gesture recognizers when the instance is about to be deallocated.Gretchengrete
Unregister from notifications and mark yourself as no longer the delegate for whatever you were the delegate for. But, yes, in ARC, you can't call [super dealloc] or, more importantly, you don't need to, as ARC is "all over it" on your behalf.Bria
B
6

In general, overriding alloc is only done when you wish to, eg, allocate an object from a pool of available instances, or perhaps allocate a variable amount of storage for the object based on some external parameter. (In C++ you can access the new parameters and allocate based on them, but Objective-C does not give you access to the initXXX parameters.)

I've never attempted any of this, and I suspect that its a bit of a minefield -- you need to study up on the structures and be pretty careful.

As Adam said, you should ALWAYS (in a reference counted environment) override dealloc if there are any retained objects held by your object.

Update: An interesting thing you can do ... in RedClass or a superclass of it code something like:

+(id)alloc {
    if (self == [RedClass class]) {
        return [BlueClass alloc];
    }
    else {
        return [super alloc];
    }
}

The net result is that whenever you execute [RedClass alloc] a BlueCLass object will be returned. (NB: Presumably BlueClass is a subclass of RedClass, or things will get seriously mucked up shortly after the object is returned.)

Not saying that it's a good idea to do this, but it's possible (and I don't offhand know of any cases where it wouldn't work reliably for vanilla user-defined classes). And it does have a few possible uses.

Additional note: In some cases one might want to use [self isSubclassOf:[RedClass class]] rather than == (though that has some serious pitfalls).

Backfire answered 29/9, 2011 at 11:44 Comment(12)
"Objective-C does not give you access to the initXXX parameters." Huh?Unsex
Objective-C doesn't prevent you from accessing anything related to alloc, but there are no parameters to alloc (other than self and _cmd), so it's not clear what you're referring to. If you meant information about instances, for example their size, the Objective-C runtime gives you access to anything and everything an implementor would need to know.Unsex
Right, there are no parameters to alloc. But C++ allows the alloc routine to access the new parameters.Backfire
@HotLicks, that's because -- as commonly used -- C++ does not make a clean distinction between allocation and initialization steps. Closest one could get is malloc()ing, memset()ting to zero, and then calling a standalone init() method.Hyp
What about objects like NSNumber that have a pool of instances for common values? I understand how [NSNumber numberWithInt:1] etc would work since we get the param before we alloc, but how does it know to return the same instance with [[NSNumber alloc] initWithInt:1]? Even with tagged pointers or all the other fancy stuff they do behind the scenes, you're still calling alloc first without any knowledge of the stored value. The only thing I can think is that calling [NSNumber alloc] returns a single shared instance and then -[NSNumber initWith...] returns the specific one. Yeah?Referee
Wicked awesome... Just as I thought. [NSNumber alloc] returns a shared instance of NSPlaceholderNumber. +[NSNumber numberWithInt:100] returns a tagged pointer so it's the same no matter how many times you call it. -[NSNumber initWithInt:100] returns the same tagged pointer.Referee
@JackLawrence -- Yep, in that case NSNumber alloc returns a dummy, and the init routine does all the work, allocating a new number instance if needed. Which is why your init routine should always use the self value returned from the super's init routine, vs the value it received on the call.Backfire
@IvanVučica -- C++ does support what amounts to a stand-alone alloc routine, it's just rarely explicitly used. However, I forget the syntax.Backfire
@HotLicks That's why I said "commonly". You could definitely just use malloc(sizeof(TheClass)) (or new with a char array, then casting it), but it's simply not done. If there's a specialized syntax which would also allow allocation without initialization on the stack instead of heap, I'd appreciate it if you'd post it if you remember it.Hyp
@IvanVučica -- IIRC, the syntax is to define a new method on your class. The first parm is the size to be allocated, and you may optionally mirror the constructor parms as additional parms to new. (But I'm recalling this from about 12 years back, so it's a little fuzzy.)Backfire
@HotLicks Overriding the new operator?! That's nasty. o_o It also still requires a malloc() inside, and it still invokes the constructor. At least from what I can tell. cprogramming.com/tutorial/operator_new.html Looks like invoking only operator new is supported, though: #2383430Hyp
@IvanVučica -- Like I said, I'm a bit vague on the details. But the function is there and it (very crudely) mirrors alloc. I used it to good effect when designing a set of sparse vector classes for data flow analysis.Backfire

© 2022 - 2024 — McMap. All rights reserved.