Re: Instance Variable access
Re: Instance Variable access
- Subject: Re: Instance Variable access
- From: Allan Odgaard <email@hidden>
- Date: Sat, 8 May 2004 20:40:37 +0200
On 8. May 2004, at 19:16, Andy Lee wrote:
So if I understand correctly, it's the *absence* of a keyword that
indicates a C++ method cannot be overridden.
Yes.
Furthermore, and hopefully I'm not screwing up again, this is not
quite like final methods in the Java sense, because in C++ a subclass
can have a non-virtual member function with the same signature. Which
means if you want an instance of the subclass to invoke its
superclass's version of the member function, you have to cast it to
the superclass.
Sort of, yes. You do something like:
struct Base {
void foo () { printf("base\n"); }
};
struct Derived : public Base {
void foo () { Base::foo(); }
};
Which means non-virtual member functions are not exactly like
methods in *any* other object-oriented language
Indeed! C++ is a multi-paradigm language and as such not *just* OO.
non-virtual member function serves the purpose of encapsulation (data
abstraction), but not polymorphism. And they are actually used quite a
lot by "modern" C++ programmers. If you look at the standard C++
library, I think that only the i/o streams portion use virtual
functions (and IMHO one of the worst designed parts of the standard
library ;) ).
-- which I'm guessing is why C++ programmers prefer the "member
function" terminology?
Also for consistency. A function in C++ can be a member function, a
template funtion, a template member function, a static member function
etc. And then you have data, where member data is attributes, but the
other qualifiers also apply to data (e.g. static member data is "class
variables" etc.).
If my new understanding is correct, I don't think it's fair to compare
performance of non-virtual member functions because they're
essentially syntactic sugar around plain old functions.
Kind of, yes. If you need dynamic typing, like in the responder chain,
informal protocols, like in the delegate pattern or similar, ObjectiveC
is the solution to the problem. If you need to introduce your new
vector or matrix type, C++ is the solution.
I doubt the hash is computed at run time every time a message is sent.
In fact, I'm pretty sure the hash is cached, perhaps inside the
structure of a SEL. The only time I can think of that a hash
definitely has to be computed at run time is if I call
NSSelectorFromString() with a variable as its argument.
Yes, you are right. The first time one needs to use a given name as a
method, one 'registers' it with the run-time and get back an opaque
pointer. And probably the pointer itself is used for hashing in the
method cache -- and in many cases, this registration only needs to be
done once.
[...] the implementation shouldn't come close to the complexity of
ObjectiveC's obj_msgSend (since C++ does not have [...]
Depends on what we mean by "close."
Here I was referring to the actual code needed to be executed. E.g. to
call foo() on our object in C++ we need to do:
obj->vtable[foo_index]();
In ObjectiveC we need something like:
cache_node* node = obj->isa->method_cache[foo_selector_id %
CACHE_SIZE];
if(node->selector == foo_selector)
node->implementation();
else /* find implementation and update cache */
What's interesting here is a) how many times we need to read memory
from a new cache line and b) how many times we branch to a new location
(and how branch-prediction may help here). As these are probably the
two dominating factors in the code.
There are some hidden branches in the ObjC-version, because it is
run-time linked and thus goes through a Mach-o stub. But even with
this, it should take significantly less than 10.000 cycles (including
all the cache misses etc.) when the method is found in the method
cache, and on a 1 GHz Machine, you have one billion cycles pr. second,
meaning you can do 100.000 method lookups pr. second, and this 10.000
cycles pr. objc_msgSend invocation is really a huge exaggeration (on
the average I think the PPC completes two instructions pr. cycle, not
counting cache misses, but someone else probably knows more about
this!).
I don't know if the difference is an order of magnitude or 2x or less,
I would think it's significantly more, but as others have already
pointed out, method lookup is generally not the bottleneck -- although
even helping the C++ compiler inline virtual member functions can in
certain applications be time well spent (thinking of the GRETA regex
library).
but it seems to me Objective-C *could* use a vtable-type
implementation where vtables happen to be changeable at run time, in
which case the difference should be pretty small.
No, this is not possible without some very huge method tables, because
each method (independent of class) must have a globally unique index.
Furthermore there is the problem of having code compiled in different
environments arrive at the same index numbers for the same method.
In any case, neither of the C-derivative languages does all the
runtime checking of message-sends that Java does.
Not sure what you mean by this? C++ does *no* checks at all, ObjC does
the same checks as Java, and even allows the object to react on
unimplemented methods (like forwarding them), which Java does not allow
for.
_______________________________________________
cocoa-dev mailing list | email@hidden
Help/Unsubscribe/Archives:
http://www.lists.apple.com/mailman/listinfo/cocoa-dev
Do not post admin requests to the list. They will be ignored.