ctl8588@rigel.tamu.edu (LAUGHLIN, CHET) (08/10/90)
Hello. I am thinking about writing a rather complex program using C++; however, I am concerned with the amount of code that I see being generated by the compiler. I am especially concerned with how compact the code will be to handle many classes of similar objects that differ only in small ways when actions are performed on them. For example, If I was to code a routine that would generate output for three types of objects it might look like this.... switch(curr_object) { case a: printf("howdy"); break; /* excuse the format...saving */ case b: printf("hello"); break; /* space here */ case c: printf("hi"); break; case d: printf("goodbye"); break; } Now, in C++ I would have a,b,and c inherit the same characteristics from some global class. From the literature I've seen I am lead to believe that all the code for an object is black boxed together...So I would see the following effect produced by the compiler. greeting(curr_object); /* Tell object to say hi */ /* apologies for bad syntax...I've not */ ..... /* actually programmed in C++ yet...*/ switch(curr_object) { /* compiler translates it to this... */ case a: actiona(); break; case b: actionb(); break; case c: actionc(); break; case d: actiond(); break; } Someone please tell me that this doesn't happen. This seems like a mountain of overhead to me to perform any actions. Apologies for any incorrect syntax/wrong usage of terms. -Chet Laughlin -- Send compilers articles to compilers@esegue.segue.boston.ma.us {spdcc | ima | lotus| world}!esegue. Meta-mail to compilers-request@esegue.
burley@world.std.com (James C Burley) (08/10/90)
In article <1990Aug09.180436.18715@esegue.segue.boston.ma.us> ctl8588@rigel.tamu.edu (LAUGHLIN, CHET) writes: Hello. I am thinking about writing a rather complex program using C++; however, I am concerned with the amount of code that I see being generated by the compiler. I am especially concerned with how compact the code will be to handle many classes of similar objects that differ only in small ways when actions are performed on them. greeting(curr_object); /* Tell object to say hi */ /* apologies for bad syntax...I've not */ ..... /* actually programmed in C++ yet...*/ switch(curr_object) { /* compiler translates it to this... */ case a: actiona(); break; case b: actionb(); break; case c: actionc(); break; case d: actiond(); break; } Someone please tell me that this doesn't happen. This seems like a mountain of overhead to me to perform any actions. Don't worry; "curr_object->greeting()" (rather than the notation you showed) produces a direct call to the desired function, unless the function is declared virtual. Without "virtual", C++ calls the function specified by what it knows at compile time about the type of "curr_object". So it should not be any different. In your specific case, however, I suspect you would WANT to use "virtual", which allows "late-binding". This means that while C++ still has a concept of which type "curr_object" is, when calling "greeting" for it, it allows for the possibility that "curr_object" is, at run time, some other object DERIVED from the base object (type of "curr_object" as known at compile time). This has the EFFECT of your switch statement, but is actually implemented (in most implementations I've heard of) using an indirect function call: (*curr_object.some_offset)(); This is, on most architectures, faster than the switch statement with a function call on each possible branch of the statement, and also smaller in terms of code size. It does, however, mean that for every virtual ("changeable for each derived class") function, there will be a pointer maintained to the appropriate function. This may be an a per-object (instance) basis; or, as I think is the case with most C++ implementations, on a per-class basis, but in that case, the call is a bit more complicated: (*curr_object.class_pointer->some_offset)(); This would be a bit slower (but save data memory space), but I still think it competes well with switch/dispatch on many architectures. In case you're wondering, the non-virtual-laden function declaration I first mentioned, providing "early binding", is not provided for in some "pure" OOP languages like Smalltalk. Conceptually, "late-binding" provides for run-time polymorphism (which function actually gets invoked by an operation depending on the run-time types of the operators involved). As I understand it, C++ defaults to early binding to provide the kind of souped-up performance C programmers have come to expect. You'll get better answers from others, I'm sure. I haven't actually written a single line of C++ yet, and only dabbled in Smalltalk. (But I watch these areas very closely as a reader of JOOP, C++ Report, Smalltalk books, other theory and practice books, and by doing my own OOP-related language designs, so I'm not a total neophyte :-) James Craig Burley, Software Craftsperson burley@world.std.com -- Send compilers articles to compilers@esegue.segue.boston.ma.us {spdcc | ima | lotus| world}!esegue. Meta-mail to compilers-request@esegue.