From rifkin@cco.caltech.edu Sun Feb 13 05:16:06 1994 To: adam@vlsi.cs.caltech.edu Subject: C++ Faq 4 >Newsgroups: comp.lang.c++ >Path: nntp-server.caltech.edu!netline-fddi.jpl.nasa.gov!elroy.jpl.nasa.gov!swrinde!cs.utexas.edu!howland.reston.ans.net!europa.eng.gtefsd.com!news.umbc.edu!eff!news.kei.com!ub!clarkson!cheetah.ece.clarkson.edu!cline >From: cline@cheetah.ece.clarkson.edu (Marshall Cline) >Subject: C++ FAQ: posting #4/4 >Message-ID: <1994Feb11.210717.299@news.clarkson.edu> >Followup-To: comp.lang.c++ >Summary: Please read this before posting to comp.lang.c++ >Sender: cline@sun.soe.clarkson.edu >Nntp-Posting-Host: cheetah.ece.clarkson.edu >Reply-To: cline@parashift.com (Marshall Cline) >Organization: Paradigm Shift, Inc (training/OOD/C++/libraries) >Date: Fri, 11 Feb 1994 21:07:17 GMT >Expires: Fri, 11 Mar 1994 21:07:17 GMT >Lines: 907 comp.lang.c++ Frequently Asked Questions list (with answers, fortunately). Copyright (C) 1991-93 Marshall P. Cline, Ph.D. Posting 4 of 4. Posting #1 explains copying permissions, (no)warranty, table-of-contents, etc ============================================================================== SECTION 16: Linkage-to/relationship-with C ============================================================================== Q102: How can I call a C function `f()' from C++ code? A: Tell the C++ compiler that it is a C function: extern "C" void f(); Be sure to include the full function prototype. A block of many C functions can be grouped via braces, as in: extern "C" { void* malloc(size_t); char* strcpy(char* dest, const char* src); int printf(const char* fmt, ...); } ============================================================================== Q103: How can I create a C++ function `f()' that is callable by my C code? A: Use the same `extern "C" f()' construct as detailed in the previous question, only then proceed to actually define the function in your C++ module. The compiler will ensure that the external information sent to the linker uses C calling conventions and name mangling (ex: preceded by a single underscore). Obviously you can't make several overloaded fns simultaneously callable by a C program, since name overloading isn't supported by C. Caveats and implementation dependencies: * your `main()' should be compiled with your C++ compiler. * your C++ compiler should direct the linking process. ============================================================================== Q104: Why's the linker giving errors for C/C++ fns being called from C++/C fns? A: See the previous two questions on how to use `extern "C"'. ============================================================================== Q105: How can I pass an object of a C++ class to/from a C function? A: Here's an example of one that will work (be sure to read the tail of this answer which details when such a scheme will *not* work): /****** C/C++ header file: X.h ******/ #ifdef __cplusplus /*`__cplusplus' is #defined iff compiler is C++*/ extern "C" { #endif #ifdef __STDC__ extern int c_fn(struct X*); /* ANSI-C prototypes */ extern struct X* cplusplus_callback_fn(struct X*); #else extern int c_fn(); /* K&R style */ extern struct X* cplusplus_callback_fn(); #endif #ifdef __cplusplus } #endif #ifdef __cplusplus class X { int a; public: X(); void frob(int); }; #endif Then, in file `X.C': #include "X.h" X::X() : a(0) { } void X::frob(int aa) { a = aa; } X* cplusplus_callback_fn(X* x) { x->frob(123); return x; } In C++ file `main.C': #include "X.h" int main() { X x; c_fn(&x); return 0; } Finally, in a C file `c-fn.c': #include "X.h" int c_fn(struct X* x) { if (cplusplus_callback_fn(x)) do_one_thing(); else do_something_else(); return something(); } Passing ptrs to C++ objects to/from C fns will FAIL if you pass and get back something that isn't *exactly* the same pointer, such as passing a base class ptr and receiving a derived class ptr (this fails when multiple inheritance is involved, since C fails to do pointer-conversion properly). ============================================================================== Q106: Can my C function access data in an object of a C++ class? A: Sometimes. (First read the previous question on passing C++ objects to/from C functions.) You can safely access a C++ object's data from a C function if the C++ class: * has no virtual functions (including inherited virtual fns) * has all its data in the same access-level section (private/protected/public) * has no fully-contained subobjects with virtual fns If the C++ class has any base classes at all (or if any fully contained subobjects have base classes), accessing the data will *technically* be non-portable, since class layout under inheritance isn't imposed by the language. However in practice, all C++ compilers do it the same way: the base class object appears first (in left-to-right order in the event of multiple inheritance), and subobjects follow. Furthermore you can often (but less than always) assume a `void*' appears in the object at the location of the first virtual function. This is trickier, since the first virtual function is often in a different access specifier section than the data members. Even the use of a single pointer is not required by the language (but this is the way `everyone' does it). If the class has any virtual base classes, it is more complicated and less portable. One common implementation technique is for objects to contain an object of the virtual base class (V) last (regardless of where `V' shows up as a virtual base class in the inheritance DAG), with the rest of the object's parts appearing in the normal order. Every class that has V as a virtual base class actually has a *pointer* to the V part of the final object. ============================================================================== Q107: Why do I feel like I'm `further from the machine' in C++ as opposed to C? A: Because you are. Being an OOPL, C++ allows you to directly model the problem domain itself (obviously OOD is more complex than this, but a good start at `finding the objects' is to model the nouns in the problem domain). By modeling the problem domain, the system interacts in the language of the problem domain rather than in the language of the solution domain. One of C's great strengths is the fact that it has `no hidden mechanism'. What you see is what you get. You can read a C program and `see' every clock cycle. This is not the case in C++; overloaded operators are a case in point. Old line C programmers (such as many of us once were) are often ambivalent about this feature, but soon we realize that it provides a level of abstraction and economy of expression which lowers maintenance costs without destroying runtime performance. Naturally you can write assembly code in any language; using C++ doesn't guarantee any particular level of quality, reusability, abstraction, or any other measure of `goodness'. C++ doesn't try to make it impossible for bad programmers to write bad programs; it enables good programmers to write good programs. ============================================================================== SECTION 17: Pointers to member functions ============================================================================== Q108: What is the type of `ptr-to-member-fn'? Is it diffn't from `ptr-to-fn'? A: A member fn of class X has type: Returntype (X::*)(Argtypes) while a plain function has type: Returntype (*) (Argtypes) ============================================================================== Q109: How can I ensure `X's objects are only created with new, not on the stack? A: Make constructors protected and define `friend' or `static' fns that return a ptr to objects created via `new' (the ctors must be protected rather than private, otherwise you couldn't derive from the class). Ex: class X { //only want to allow dynamicly allocated X's public: static X* create() { return new X(); } static X* create(int i) { return new X(i); } static X* create(const X& x) { return new X(x); } protected: X(); X(int i); X(const X& x); virtual ~X(); }; X* Xptr = X::create(5); ============================================================================== Q110: How do I pass a ptr to member fn to a signal handler,X event callback,etc? A: Because a member function is meaningless without an object to invoke it on, you can't do this directly (if `X' were rewritten in C++, it would probably pass references to *objects* around, not just pointers to fns; naturally the objects would embody the required function and probably a whole lot more). As a patch for existing software, use a free function as a wrapper which takes an object obtained through some other technique (held in a global, perhaps) and calls the desired member function. There is one exception: static member functions do not require an actual object to be invoked, and ptrs-to-static- member-fns are type compatible with regular ptrs-to-fns (see ARM p.25, 158). Ex: suppose you want to call X::memfn() on interrupt: class X { public: void memfn(); static void staticmemfn(); //a static member fn can handle it //... }; //wrapper fn remembers the object on which to invoke memfn in a static var: static X* object_which_will_handle_signal; void X_memfn_wrapper() { object_which_will_handle_signal.memfn(); } main() { /* signal(SIGINT, X::memfn); */ //Can NOT do this signal(SIGINT, X_memfn_wrapper); //Ok signal(SIGINT, X::staticmemfn); //Also Ok } ============================================================================== Q111: Why am I having trouble taking the address of a C++ function? Short ans: Please read previous question first; this is a corollary. Long ans: In C++, member fns have an implicit parameter which points to the object (the `this' ptr inside the member fn). Normal C fns can be thought of as having a different calling convention from member fns, so the types of their ptrs (ptr-to-member-fn vs ptr-to-fn) are different and incompatible. C++ introduces a new type of ptr, called a ptr-to-member, which can only be invoked by providing an object (see ARM 5.5). Do NOT attempt to `cast' a ptr-to-mem-fn into a ptr-to-fn; the result is undefined and probably disastrous; a ptr-to- member-fn is NOT required to contain the machine addr of the appropriate fn (see ARM, 8.1.2c, p.158). As was said in the last example, if you want a regular C fn ptr, use either a top-level (non-class) fn, or a `static' (class) member fn. ============================================================================== Q112: How do I declare an array of pointers to member functions? A: Use the following declaration: class Frob { public: Rettype f(T1 x, T2 y); Rettype g(T1 x, T2 y); Rettype h(T1 x, T2 y); Rettype i(T1 x, T2 y); //... }; Rettype (Frob::*fn_ptr[3])(T1,T2) = { &Frob::f, &Frob::g, &Frob::h }; You can make the array declaration somewhat clearer with a typedef: typedef Rettype (Frob::*Frob_member_ptr)(T1,T2); //... Frob_member_ptr fn_ptr[3] = { &Frob::f, &Frob::g, &Frob::h }; To call one of the functions on an object `frob', use: Frob frob; //... (frob.*fn_ptr[i])(x, y); You can make the call somewhat clearer using a #define: #define apply_member_fn(object,fn) ((object).*(fn)) //... apply_member_fn(frob,fn_ptr[i])(x, y) ============================================================================== SECTION 18: Container classes and templates ============================================================================== Q113: How can I insert/access/change elements from a linked list/hashtable/etc? A: I'll use a `inserting into a linked list' as a prototypical example. The obvious approach is to allow insertion at the head and tail of the list, but that would produce a library that is too weak (a weak library is almost worse than no library). Whenever encapsulation frustrates rather than helps a user, it may be that the class' public interface needs enhancing. If class List only supports adding at the front and tail, it *definitely* needs more strength. This answer will be a lot to swallow for novice C++'ers, so I'll give a couple of options. As usual, the first is easiest, while the second option is better. I also give a thumbnail sketch of a third option, which has certain advantages and disadvantages over the second option. [1] Empower the List with a `viewport' or `cursor' that references an arbitrary list element. Implies adding member fns to List such as advance(), backup(), atend(), atbegin(), rewind(), fastforward(), and current(). `current()' returns the element of the List that is currently `under the cursor'. Finally you'll need to add a few more member fns to *mutate* the list, such as changeto(X), insert(X), remove(), etc. [2] Provide a separate class called ListIter. ListIter has member fns named similar to the above (though probably with operator overloading, but that's just syntactic sugar for member fns). The List itself would have none of the above mentioned member fns, and the ListIter would be a `friend' of List (ListIter would have to have access to the innards of List; this allows the world to have safe access abilities to List without violating encapsulation). The reason option [2] is better becomes apparent when you use classes that only support [1]. In particular, if you pass a List off to a subcall, you'd better hope the subcall didn't warp the `cursor' around, or your code may fail. Also, if you try to get all pairs of elements, it's very hard if you only have one cursor. The distinct-class iterator concept removes these restrictions. My own class library uses these extensively, as will most any other commercial grade class library. Note that the options are not mutually exclusive; it is possible to provide both [2] *and* [1], giving rise to the notion of a `primary' list position, with instances of ListIter being somewhat secondary. [3] The third possibility considers the entire iteration as an atomic event. A class is created which embodies this event. The nice thing about this third alternative is that the public access methods (which may be virtual fns) can be avoided during the inner loop, thus enhancing performance. The down side is that you get extra object code in the application, since templates gain speed by duplicating code. This third technique is due to Andrew Koenig in a paper published recently in JOOP [`Templates as interfaces', JOOP, 4, 5 (Sept 91)]. You can also see a taste of it in Bjarne Stroustrup's book, The C++ Programming Language Second Edition (look for `Comparator' in the index). ============================================================================== Q114: What's the idea behind `templates'? A: A template is a cookie-cutter that specifies how to cut cookies that all look pretty much the same (although the cookies can be made of various kinds of dough, they'll all have the same basic shape). In the same way, a class template is a cookie cutter to description of how to build classes that all look basically the same, and a function template describes how to build similar looking functions. The questions about templates are in the `Containers' section since templates are often used to build type safe containers (although this only scratches the surface for how they can be used). We will see how to use templates to build container classes below. ============================================================================== Q115: What's the syntax / semantics for a `function template'? A: Consider this function that swaps its two integer arguments: void swap(int& x, int& y) { int tmp = x; x = y; y = tmp; } If we also had to swap floats, longs, Strings, Sets, and FileSystems, we'd get pretty tired of coding lines that look almost identical except for the type. Mindless repetition is an ideal job for a computer, hence a function template: template void swap(T& x, T& y) { T tmp = x; x = y; y = tmp; } Every time we used `swap()' with a given pair of types, the compiler will go to the above definition and will create yet another `template function' as an instantiation of the above. Ex: main() { int i,j; /*...*/ swap(i,j); //instantiates a swap for `int' float a,b; /*...*/ swap(a,b); //instantiates a swap for `float' char c,d; /*...*/ swap(c,d); //instantiates a swap for `char' String s,t; /*...*/ swap(s,t); //instantiates a swap for `String' } (note: a `template function' is the instantiation of a `function template'). ============================================================================== Q116: What's the syntax / semantics for a `class template'? A: Consider this container class of that acts like an array of integers: //this would go into a header file such as `Vec.h': class Vec { public: int len() const { return xlen; } const int& operator[](int i) const { xdata[check(i)]; } int& operator[](int i) { xdata[check(i)]; } Vec(int L=10) : xlen(L), xdata(new int[L]) { /*verify*/ } ~Vec() { delete [] xdata; } private: int xlen; int* xdata; int check(int i); //return i if i>=0 && i= xlen) throw BoundsViol("Vec", i, xlen); return i; } Just as with `swap()' above, repeating the above over and over for Vec of float, char, String, Vec, Vec-of-Vec-of-Vec, etc, will become tedious. Hence we create a single class template: //this would go into a header file such as `Vec.h': template class Vec { public: int len() const { return xlen; } const T& operator[](int i) const { xdata[check(i)]; } T& operator[](int i) { xdata[check(i)]; } Vec(int L=10) : xlen(L), xdata(new T[L]) { /*verify*/ } ~Vec() { delete [] xdata; } private: int xlen; T* xdata; int check(int i); //return i if i>=0 && i int Vec::check(int i) { if (i < 0 || i >= xlen) throw BoundsViol("Vec", i, xlen); return i; } Unlike template functions, template classes (instantiations of class templates) need to be explicit about the parameters over which they are instantiating: main() { Vec vi; Vec vf; Vec vc; Vec vs; Vec< Vec > vv; } // ^^^-- note the space; do NOT use Vec> since the // `maximal munch' rule would grab a single `>>' token ============================================================================== Q117: What is a `parameterized type'? A: A parameterized type is a type that is parameterized over another value or type. Ex: List is a type that is parameterized over another type, `int'. Therefore the C++ rendition of parameterized types is provided by class templates. ============================================================================== Q118: What is `genericity'? A: Not to be confused with `generality' (which just means avoiding solutions which are overly specific), `genericity' means parameterized types. In C++, this is provided by class templates. ============================================================================== Q119: How can I fake templates if I don't have a compiler that supports them? A: The best answer is: buy a compiler that supports templates. When this is not feasible, the next best answer is to buy or build a template preprocessor (ex: reads C++-with-templates, outputs C++-with-expanded-template-classes; such a system needn't be perfect; it cost my company about three man-weeks to develop such a preprocessor). If neither of these is feasible, you can use the macro preprocessor to fake templates. But beware: it's tedious; templates are a better solution wrt development and maintenance costs. Here's how you'd declare my `Vec' example from above. First we define `Vec(T)' to concatenate the name `Vec' with that of the type T (ex: Vec(String) becomes `VecString'). This would go into a header file such as Vec.h: #include //to get the `name2()' macro #define Vec(T) name2(Vec,T) Next we declare the class Vec(T) using the name `Vecdeclare(T)' (in general you would postfix the name of the class with `declare', such as `Listdeclare' etc): #define Vecdeclare(T) \ class Vec(T) { \ int xlen; \ T* xdata; \ int check(int i); /*return i if in bounds else throw*/ \ public: \ int len() const { return xlen; } \ const T& operator[](int i) const { xdata[check(i)]; } \ T& operator[](int i) { xdata[check(i)]; } \ Vec(T)(int L=10): xlen(L), xdata(new T[L]) {/*...*/}\ ~Vec(T)() { delete [] xdata; } \ }; Note how each occurrence of `Vec' has the `(T)' postfixed. Finally we set up another macro that `implements' the non-inline member function(s) of Vec: //strangely enough this can also go into Vec.h #define Vecimplement(T) \ int Vec(T)::check(int i) \ { \ if (i < 0 || i >= xlen) throw BoundsViol("Vec", i, xlen); \ return i; \ } When you wish to use a Vec-of-String and Vec-of-int, you would say: #include "Vec.h" //pulls in too; see below... declare(Vec,String) //`declare()' is a macro defined in declare(Vec,int) Vec(String) vs; //Vec(String) becomes the single token `VecString' Vec(int) vi; In exactly one source file in the system, you must provide implementations for the non-inlined member functions: #include "Vec.h" declare (Vec,String) declare (Vec,int) declare (Vec,float) implement(Vec,String) implement(Vec,int) implement(Vec,float) Note that types whose names are other than a single identifier do not work properly. Ex: Vec(char*) creates a class whose name is `Vecchar*'. The patch is to create a typedef for the appropriate type: #include "Vec.h" typedef char* charP; declare(Vec,charP) It is important that every declaration of what amounts to `Vec' must all use exactly the same typedef, otherwise you will end up with several equivalent classes, and you'll have unnecessary code duplication. This is the sort of tedium which a template mechanism can handle for you. ============================================================================== SECTION 19: Nuances of particular implementations ============================================================================== Q120: Why don't variable arg lists work for C++ on a Sun SPARCstation? A: That is a bug in cfront 2.1. There is a magic variable, __builtin_va_alist. It has to be added to the end of the argument list of a varadic function, and it has to be referenced in va_start. This requires source modification to (a) print `,__builtin_va_alist' on the end of the argument list, (b) pretend that this arg was declared, and thus pass references to it, and (c) not mangle its name in the process. Here's a tiny bit more detail: 1) when print2.c prints a varadic procedure, it should add __builtin_va_alist to the end. It need not declare it. Type of int to the Sun C compiler (the default) is fine. 2) #define va_start(ap,parmN) ap = (char *)&__builtin_va_alist 3) when find.c see this reference to __builtin_va_alist, it should construct a special cfront name node. When name::print sees that node it should print its name literally, without adding any mangling. 4) the same trick is needed, with the name va_alist, for Ultrix/MIPS and HPUX. 5) the net result, in generated C code, looks like: void var_proc (a, b, c, __builtin_va_alist) int a; float b; char * c; { char * val; val = &__builtin_va_alist; ... } ============================================================================== Q121: GNU C++ (g++) produces big executables for tiny programs; Why? A: libg++ (the library used by g++) was probably compiled with debug info (-g). On some machines, recompiling libg++ without debugging can save lots of disk space (~1 Meg; the down-side: you'll be unable to trace into libg++ calls). Merely `strip'ping the executable doesn't reclaim as much as recompiling without -g followed by subsequent `strip'ping the resultant `a.out's. Use `size a.out' to see how big the program code and data segments really are rather than `ls -s a.out' which includes the symbol table. ============================================================================== Q122: Is there a yacc-able C++ grammar? A: Jim Roskind is the author of a yacc grammar for C++. It's roughly compatible with the portion of the language implemented by USL cfront 2.0. Jim's grammar deviates from cfront (and the ARM) in a couple of what I understand to be minor ways. Ultimately any deviation from a standard is unthinkable, but the number of real programs that are interpreted differently is relatively small, so the `consequence' of the deviation is not great. I have used Jim's grammar when a grad student wrote a C++ templatizer mechanism (reads ANSI-C++, spits out pre-templates C++), but my expertise does not include precise knowledge of where the grammar deviates from `official'. I have found it to parse most things correctly, but I am aware that there are differences. (is that noncommittal enough? :-) The grammar can be accessed by anonymous ftp from the following sites: * ics.uci.edu (128.195.1.1) in the ftp/gnu directory (even though neither of the archives are GNU related) as: c++grammar2.0.tar.Z and byacc1.8.tar.Z * mach1.npac.syr.edu (128.230.7.14) in the ftp/pub/C++ directory as: c++grammar2.0.tar.Z and byacc1.8.tar.z Jim Roskind can be reached at jar@hq.ileaf.com or ...!uunet!leafusa!jar ============================================================================== Q123: What is C++ 1.2? 2.0? 2.1? 3.0? A: These are not versions of the language, but rather versions of the USL translator, cfront. However many people discuss these as levels of the language as well, since each of the above versions represents additions to the portion of the C++ language which is implemented by the compiler. When ANSI/ISO C++ is finalized, conformance with the ANSI/ISO spec will become more important than conformance with cfront version X.Y, but presently, cfront is acting as a de facto standard to help coordinate the industry (although it leaves certain features of the language unimplemented as well). *VERY* roughly speaking, these are the major features: * 2.0 includes multiple/virtual inheritance and pure virtual functions. * 2.1 includes semi-nested classes and `delete [] ptr_to_array'. * 3.0 includes fully-nested classes, templates and `i++' vs `++i'. *?4.0? will include exceptions. ============================================================================== Q124: How does the lang accepted by cfront 3.0 differ from that accepted by 2.1? A: USL cfront release 3.0 provides implementations of a number of features that were previously flagged as `sorry not implemented': templates, fully nested types, prefix and postfix increment and decrement operators, initialization of single dimension arrays of class objects with ctors taking all default arguments, use of operators &&, ||, and ?: with expressions requiring temporaries of class objects containing destructors, and implicit named return values. The major feature not accepted by cfront 3.0 is exceptions. ============================================================================== Q125: Why are exceptions going to be implemented after templates? Why not both? A: Most C++ compiler vendors are providing templates in their present release, but very few are providing exceptions (I know of only one). The reason for going slowly is that both templates and exception handling are difficult to implement *well*. A poor template implementation will give slow compile and link times and a poor exception handling implementation will give slow run times. Good implementations will not have those problems. C++ compiler vendors are human beings too, and they can only get so much done at once. However they know that the C++ community is craving for the `whole' language, so they'll be pushing hard to fill that need. ============================================================================== Q126: What was C++ 1.xx, and how is it different from the current C++ language? A: C++ 1.2 (the version number corresponds to the release number of USL's cfront) corresponds to Bjarne Stroustrup's first edition (`The C++ Programming Language', ISBN 0-201-12078-X). In contrast, the present version (3.0) corresponds roughly to the `ARM', except for exceptions. Here is a summary of the differences between the first edition of Bjarne's book and the ARM: - A class can have more than one direct base class (multiple inheritance). - Class members can be `protected'. - Pointers to class members can be declared and used. - Operators `new' and `delete' can be overloaded and declared for a class. This allows the "assignment to `this'" technique for class specific specific storage management to be removed to the anachronism section - Objects can be explicitly destroyed. - Assignment and Copy-Initialization default to member-wise assignment and copy-initialization. - The `overload' keyword was made redundant and removed to the anachronism section. - General expressions are allowed as initializers for static objects. - Data objects can be `volatile' (new keyword). - Initializers are allowed for `static' class members. - Member functions can be `static'. - Member functions can be `const' or `volatile'. - Linkage to non-C++ program fragments can be explicitly declared. - Operators `->', `->*' and `,' can be overloaded. - Classes can be abstract. - Prefix and postfix application of `++' and `--' on a user-defined type can be distinguished. - Templates. - Exception handling. ============================================================================== SECTION 20: Miscellaneous technical and environmental issues ============================================================================== SUBSECTION 20A: Miscellaneous technical issues: ============================================================================== Q127: Why are classes with static data members getting linker errors? A: Static member variables must be given an explicit definition in exactly one module. Ex: class X { //... static int i; //*declare* static member X::i //... }; The linker will holler at you (`X::i is not defined') unless (exactly) one of your source files has something like the following: int X::i = some_expression_evaluating_to_an_int; //*define* X::i or: int X::i; //define --but don't initialize-- X::i The usual place to define static member variables of class `X' is file `X.C' (or X.cpp, X.cc, X.c++, X.c or X.cxx; see question on file naming conventions). ============================================================================== Q128: What's the difference between the keywords struct and class? A: The members and base classes of a struct are public by default, while in class, they default to private. Base classes of a struct are public by default while they are private by default with `class' (however you should make your base classes *explicitly* public, private, or protected). `Struct' and `class' are otherwise functionally equivalent. ============================================================================== Q129: Why can't I overload a function by its return type? Ex: the compiler says the following two are an error: char f(int i); float f(int i); A: Return types are not considered when determining unique signatures for overloading functions; only the number and type of parameters are considered. Reason: which function should be called if the return value is ignored? Ex: main() { f(3); //which should be invoked?? } ============================================================================== Q130: What is `persistence'? What is a `persistent object'? A: Loosely speaking, a persistent object is one that lives on after the program which created it has stopped. Persistent objects can even outlive various versions of the creating program, can outlive the disk system, the operating system, or even the hardware on which the OS was running when they were created. The challenge with persistent objects is to effectively store their method code out on secondary storage along with their data bits (and the data bits and method code of all subobjects, and of all their subobjects, etc). This is non-trivial when you have to do it yourself. In C++, you have to do it yourself. C++/OO databases can help hide the mechanism for all this. ============================================================================== SUBSECTION 20B: Miscellaneous environmental issues: ============================================================================== Q131: Is there a TeX or LaTeX macro that fixes the spacing on `C++'? A: Yes, here are two: \def\CC{C\raise.22ex\hbox{{\footnotesize +}}\raise.22ex\hbox{\footnotesize +}} \def\CC{{C\hspace{-.05em}\raisebox{.4ex}{\tiny\bf ++}}} ============================================================================== Q132: Where can I access C++2LaTeX, a LaTeX pretty printer for C++ source? A: Here are a few ftp locations: Host aix370.rrz.uni-koeln.de (134.95.80.1) Last updated 15:41 26 Apr 1991 Location: /tex FILE rw-rw-r-- 59855 May 5 1990 C++2LaTeX-1.1.tar.Z Host utsun.s.u-tokyo.ac.jp (133.11.11.11) Last updated 05:06 20 Apr 1991 Location: /TeX/macros FILE rw-r--r-- 59855 Mar 4 08:16 C++2LaTeX-1.1.tar.Z Host nuri.inria.fr (128.93.1.26) Last updated 05:23 9 Apr 1991 Location: /TeX/tools FILE rw-rw-r-- 59855 Oct 23 16:05 C++2LaTeX-1.1.tar.Z Host iamsun.unibe.ch (130.92.64.10) Last updated 05:06 4 Apr 1991 Location: /TeX FILE rw-r--r-- 59855 Apr 25 1990 C++2LaTeX-1.1.tar.Z Host iamsun.unibe.ch (130.92.64.10) Last updated 05:06 4 Apr 1991 Location: /TeX FILE rw-r--r-- 51737 Apr 30 1990 C++2LaTeX-1.1-PL1.tar.Z Host tupac-amaru.informatik.rwth-aachen.de (192.35.229.9) Last updated 05:07 18 Apr 1991 Location: /pub/textproc/TeX FILE rw-r--r-- 72957 Oct 25 13:51 C++2LaTeX-1.1-PL4.tar.Z Host wuarchive.wustl.edu (128.252.135.4) Last updated 23:25 30 Apr 1991 Location: /packages/tex/tex/192.35.229.9/textproc/TeX FILE rw-rw-r-- 49104 Apr 10 1990 C++2LaTeX-PL2.tar.Z FILE rw-rw-r-- 25835 Apr 10 1990 C++2LaTeX.tar.Z Host tupac-amaru.informatik.rwth-aachen.de (192.35.229.9) Last updated 05:07 18 Apr 1991 Location: /pub/textproc/TeX FILE rw-r--r-- 74015 Mar 22 16:23 C++2LaTeX-1.1-PL5.tar.Z Location: /pub FILE rw-r--r-- 74015 Mar 22 16:23 C++2LaTeX-1.1-PL5.tar.Z Host sol.cs.ruu.nl (131.211.80.5) Last updated 05:10 15 Apr 1991 Location: /TEX/TOOLS FILE rw-r--r-- 74015 Apr 4 21:02x C++2LaTeX-1.1-PL5.tar.Z Host tupac-amaru.informatik.rwth-aachen.de (192.35.229.9) Last updated 05:07 18 Apr 1991 Location: /pub/textproc/TeX FILE rw-r--r-- 4792 Sep 11 1990 C++2LaTeX-1.1-patch#1 FILE rw-r--r-- 2385 Sep 11 1990 C++2LaTeX-1.1-patch#2 FILE rw-r--r-- 5069 Sep 11 1990 C++2LaTeX-1.1-patch#3 FILE rw-r--r-- 1587 Oct 25 13:58 C++2LaTeX-1.1-patch#4 FILE rw-r--r-- 8869 Mar 22 16:23 C++2LaTeX-1.1-patch#5 FILE rw-r--r-- 1869 Mar 22 16:23 C++2LaTeX.README Host rusmv1.rus.uni-stuttgart.de (129.69.1.12) Last updated 05:13 13 Apr 1991 Location: /soft/tex/utilities FILE rw-rw-r-- 163840 Jul 16 1990 C++2LaTeX-1.1.tar ============================================================================== Q133: Where can I access `tgrind', a pretty printer for C++/C/etc source? A: `tgrind' reads the file to be printed and a command line switch to see what the source language is. It then reads a language definition database file and learns the syntax of the language (list of keywords, literal string delimiters, comment delimiters, etc). `tgrind' usually comes with the public distribution of TeX and LaTeX. Look in the directory: ...tex82/contrib/van/tgrind A more up-to-date version of tgrind by Jerry Leichter can be found on: venus.ycc.yale.edu in [.TGRIND] ============================================================================== Q134: Is there a C++-mode for GNU emacs? If so, where can I get it? A: Yes, there is a C++-mode for GNU emacs. You can get it via: c++-mode-2 (1.0) 87-12-08 Bruce Eckel,Thomas Keffer, archive.cis.ohio-state.edu:/pub/gnu/emacs/elisp-archive/as-is/c++-mode-2.el.Z Another C++ major mode. c++-mode 89-11-07 Dave Detlefs, et al, archive.cis.ohio-state.edu:/pub/gnu/emacs/elisp-archive/modes/c++-mode.el.Z C++ major mode. c++ 90-02-01 David Detlefs, Stewart Clamen, archive.cis.ohio-state.edu:/pub/gnu/emacs/elisp-archive/modes/c++.el.Z C++ code editing commands for Emacs c-support (46) 89-11-04 Lynn Slater, archive.cis.ohio-state.edu:/pub/gnu/emacs/elisp-archive/misc/c-support.el.Z Partial support for team C/C++ development. ============================================================================== Q135: What is `InterViews'? A: A non-proprietary toolkit for graphic user interface programming in C++, developed by Mark Linton and others when he was at Stanford. Unlike C++ wrappers for C libraries such as Motif, InterViews is a true object library. Commercially maintained versions are available from Quest, while freely redistributable versions (running on top of X) from interviews.stanford.edu (an ftp site). Copies of this are (were?) distributed with the regular X distribution. Other sources of information include comp.windows.interviews, which has its own FAQ. ============================================================================== Q136: Where can I get OS-specific questions answered (ex:BC++,DOS,Windows,etc)? A: see comp.os.msdos.programmer, BC++ and Zortech mailing lists, BC++ and Zortech bug lists, comp.windows.ms.programmer, comp.unix.programmer, etc. You can subscribe to the BC++ mailing list by sending email to: | To: listserv@ucf1vm.cc.ucf.edu <---or LISTSERV@UCF1VM.BITNET | Subject: SUB TCPLUS-L | Reply-to: you@your.email.addr <---ie: put your return address here The BC++ bug report is available via anonymous ftp from sun.soe.clarkson.edu [128.153.12.3] from the file ~ftp/pub/Turbo-C++/bug-report (also, I post it on comp.lang.c++ on the first each month). Relevant email addresses: ztc-list@zortech.com General requests and discussion ztc-list-request@zortech.com Requests to be added to ztc-list ztc-bugs@zortech.com For _short_ bug reports ============================================================================== Q137: Why does my DOS C++ program says `Sorry: floating point code not linked'? A: The compiler attempts to save space in the executable by not including the float-to-string format conversion routines unless they are necessary, and sometimes does not recognize some code that does require it. Taking the address of a float in an argument list of a function call seems to trigger it, but taking the address of a float element of a struct may fool the compiler. A "%f" in a printf/scanf format string doesn't trigger it because format strings aren't examined at compile-time. You can fix it by (1) using instead of , or (2) by including the following function definition somewhere in your compilation (but don't call it!): static void dummyfloat(float *x) { float y; dummyfloat(&y); } See question on stream I/O for more reasons to use vs . ============================================================================== -- Marshall Cline -- Marshall P. Cline, Ph.D. / Paradigm Shift Inc / PO Box 5108 / Potsdam NY 13676 cline@parashift.com / 315-353-6100 / FAX: 315-353-6110