United States    
COMPAQ STORE | PRODUCTS |
SERVICES | SUPPORT | CONTACT US | SEARCH
cxxtitle.gif (12116 bytes)
Compaq C++

Compaq C++
Using Compaq C++ for Tru64 UNIX Systems


Previous Contents Index

2.3.17.2 Nonconstant Reference Initialization with a Temporary Object

If your program tries to initialize a nonconstant reference with a temporary object, the compiler generates a warning. For example:


struct A { 
  A(int); 
}; 
void f(A& ar); 
 
void g() { 
  f(5);  // warning!! 
} 

2.3.17.3 Static Member Functions Selected by Expressions Creating Temporary Objects

When a static member is accessed through a member access operator, the expression on the left side of the dot (.) or right arrow (->) is not evaluated. In such cases, the compiler creates code that calls the static member function to handle the destruction of a class type temporary; the compiler does not create temporary destructor code. For example:


struct A { 
        ~A(); 
        static void sf(); 
}; 
 
struct B { 
        A operator ()() const; 
}; 
 
void f () { 
    B bobj; 
    bobj().sf();        // If 'bobj()' is evaluated, a temporary of 
                        // type 'A' is created. 
} 

2.3.18 Exception Handling (§r.15)

Compaq C++ optimizes the implementation of exception handling for normal execution, as follows:

In Compaq C++, a procedure with handlers has no intrinsic overhead. For example, procedures with handlers do not have frame pointers or additional register usage.

Some procedures without explicit handlers may have implicit handlers. The compiler creates a handler for each automatic object that has a destructor. The compiler also creates handlers for constructors that initialize subobjects that have destructors. In such a constructor, the compiler creates a handler for each member with a destructor, and a handler for each base class with a destructor.

The -nocleanup option suppresses generation of such implicit handlers, which results in an executable file that is slightly smaller. You should use this option for programs that do not use exception handling or that do not require destruction of automatic objects during exception processing.

Exception specifications in function prototypes that conflict with function definitions are illegal. Chapter 7 describes how Compaq C++ handles such conflicts. Beware of such conflicting exception specifications, particularly if you have exception specifications in prototypes that are in header files accessible to other programs.

2.3.19 File Inclusion (§r.16.4)

The #include directive inserts external text into the macro stream delivered to the Compaq C++ compiler. Programmers often use this directive to include global definitions for use with Compaq C++ functions and macros in the program stream.

The #include directive has the following search path semantics:


Chapter 3
Compaq C++ Language Environment

This chapter describes the guidelines and procedures for customizing your language environment. It includes sections on changing your C header files to work with C++, using 32-bit pointers, organizing your C++ files, interfacing to other programming languages, and designing upwardly compatible C++ classes.

3.1 Using Existing C Header Files

C header files that already conform to ANSI C standards must be slightly modified for use by Compaq C++ programs. In particular, be sure to address the following issues:

The following sections provide details on how to properly modify your header files.

3.1.1 Providing C and C++ Linkage

To modify header files, use conditional compilation and the extern specifier.

When programming header files to be used for both C and C++ programs, use the following convention for predefined macros. The system header files also provide an example of correct usage of the predefined macros.


#if defined __cplusplus 
    /* If the functions in this header have C linkage, this 
     * will specify linkage for all C++ language compilers. 
     */ 
    extern "C" { 
#endif 
 
extern int func1(int); 
extern int func2(int); 
   .
   .
   .
#if defined __cplusplus 
    }   /* matches the linkage specification at the beginning. */ 
#endif 

See §r.7.4 of The C++ Programming Language, 2nd Edition for more information on linkage specifications.

3.1.2 Resolving C++ Keyword Conflicts

If your program uses any of the following C++ language keywords as identifiers, you must replace them with nonconflicting identifiers:
asm friend private this
catch inline protected throw
class new public try
delete operator template virtual

3.1.3 Handling Scoping Issues

Distinctions between ANSI C and C++ include slight differences in rules concerning scope. Therefore, you may need to modify some ANSI C header files to use them with C++.

The following sample code fragment generates an error regarding incompatible types, but the root cause is the difference in scope rules between C and C++. In ANSI C, the compiler promotes tag names defined in structure or union declarations to the containing block or file scope. This does not happen in C++.


struct Screen { 
  struct _XDisplay *display; 
}; 
typedef struct _XDisplay { 
  // ...
} Display; 
 
struct Screen s1; 
Display      *s2; 
 
main() 
{ 
  s1.display = s2; 
}    

The offending line in this sample is s1.display = s2. The types of s1.display and s2 are the same in C but different in C++. You can solve the problem by adding the declaration struct _XDisplay; to the beginning of this code fragment, as follows:


struct _XDisplay; // this is the added line 
struct Screen { 
struct _XDisplay *display; 
}; 
typedef struct _XDisplay { 
  // ...
} Display; 
// ...

3.1.4 Support for <stdarg.h> and <varargs.h> Header Files

DEC C has special built-in macros defined in the header files <stdarg.h> and <varargs.h> . These step through the argument list of a routine.

Programs that take the address of a parameter, and use pointer arithmetic to step through the argument list to obtain the value of other parameters, assume that all arguments reside on the stack and that arguments appear in increasing order. These assumptions are not valid for Compaq C++. Furthermore, the macros in <varargs.h> can be used only by C functions with old-style definitions that are not legal in C++. To reference variable-length argument lists, use the <stdarg.h> header file.

3.2 Using Compaq C++ with Other Languages

The following are suggestions regarding the use of Compaq C++ with other languages:

3.3 Linkage to Non-C++ Code and Data

With linkage specifications, you can both import code and data written in other languages into a Compaq C++ program and export Compaq C++ code and data for use with other languages. See §4.4 of The C++ Programming Language, 2nd Edition for details on the extern "C" declaration.

3.4 How to Organize Your C++ Code

This section explains the best way for Compaq C++ users to organize an application into files; it assumes that you are using automatic instantiation to instantiate any template classes and functions.

3.4.1 Code That Does Not Use Templates

The general rule is to place declarations in header files and place definitions in library source files. Thus, the following items belong in header files:

The following items belong in library source files:

Header files should be directly included by modules that need them. Because several modules may include the same header file, a header file must not contain definitions that would generate multiply defined symbols when all the modules are linked together.

Library source files should be compiled individually and then linked into your application. Because each library source file is compiled only once, the definitions it contains will exist in only one object module and multiply defined symbols are thus avoided.

For example, to create a class called "array" you would create the following two files:

Header file, array.h:


// array.h 
#ifndef ARRAY_H 
#define ARRAY_H 
 
class array { 
private: 
        int curr_size; 
        static int max_array_size; 
public: 
        array() :curr_size(0) {;}  
        array(int); 
}; 
 
#endif 

Library source file, array.cxx:


// array.cxx 
#include "array.h" 
 
int array::max_array_size = 256; 
 
array::array(int size) :  curr_size(size) { ...;  } 

You would then compile the array.cxx library source file using the following command:


cxx -I./include array.cxx 
 

The resulting object file could either be linked directly into your application or placed in a library (see Section 3.4.4).

Note that the header file uses header guards, which is a technique to prevent multiple inclusion of the same header file.

3.4.2 Code That Uses Templates

With the widespread use of templates in C++, determining the proper place to put declarations and definitions becomes more complicated.

Two new types of header files are introduced in Chapter 5: template declaration files and template definition files. Again, the general rule is to place declarations in template declaration files and definitions in template definition files.

Thus, the following items belong in template declaration files:

The following items belong in template definition files:

These guidelines also apply to nontemplate nested classes inside of template classes.

Note

Do not place definitions of nontemplate class members, nontemplate functions, or global data within template definition files; these must be placed in library source files.

The first three items in the previous list can optionally be placed at the bottom of the template declaration file that contains the corresponding declarations. This will not incur multiply defined symbols when the template declaration file is included by multiple modules. However, this option does not apply to template specialization definitions; these must be placed in a definition template file, or optionally they can be treated as nontemplate code and placed in a library source file as described in Section 3.4.1.

The template definition file should have the same base name as the template declaration file but with a different file extension (such as .cxx). Your template declaration files and template definition files should be placed in the same directory.

For example, the array class from Section 3.4.1, modified to use templates, would now look as follows:

Template declaration file, array.h:


// array.h 
#ifndef ARRAY_H 
#define ARRAY_H 
 
template <class T> 
class array { 
private: 
        int curr_size; 
        static int max_array_size; 
public: 
        array() :curr_size(0) {;} 
        array(T); 
};  
 
#endif 

Template definition file, array.cxx:


 
// array.cxx 
template <class T> 
int array<T>::max_array_size = 256; 
 
template <class T> 
array<T>::array(int size) :  curr_size(size) { ; } 
 

Then you would create a source file myprog.cxx that uses the array class as follows:


// myprog.cxx 
 
#include <array.h> 
 
main() { 
        array<int> ai; 
 
        // ...
} 

Figure 3-1 shows the placement of these files.

Figure 3-1 Placement of Template Declaration and Definition Files


You would then compile myprog.cxx with the following command:


cxx -I include myprog.cxx 
 

In this case, you do not need to create library source files because the static member data and out-of-line members of the array template class are instantiated at the time you compile myprog.cxx.

However you would need to create library source files for the following cases:

3.4.3 Summary of Guidelines for Placing Definitions and Declarations

Table 3-1 describes where to place declarations and definitions, as discussed in Section 3.4.1 and Section 3.4.2.

Table 3-1 Declaring and Defining Classes, Functions, and Data
Feature Declaration Out-of-Line Definition
Class Header file  
Static member data Within class declaration Library source file
Member function Within class declaration Library source file
Global function Header file Library source file
Global data Header file Library source file
     
Template class Template declaration file  
Static member data of template class Within template class declaration Template definition file
Member function of template class Within template class declaration Template definition file
Global template function Template declaration file Template definition file
Global, nontemplate friend function of template class Within template class declaration Library source file
Specialization of template class Template declaration file  
Specialization of template function Template declaration file Library source file

3.4.4 Creating Libraries

Libraries are useful for organizing the sources within your application as well as for providing a set of routines for other applications to use. Libraries can be either object libraries or shareable libraries. Use an object library when you want the library code to be contained within an application's image; use shareable libraries when you want multiple applications to share the same library code.

Creating a library from nontemplate code is straightforward: you simply compile each library source file and place the resulting object file in your library.

Creating a library from template code requires that you explicitly request the instantiations that you want to provide in your library. See Chapter 6 for details on how to do this.

If you make your library available to other users, you must also supply the corresponding declarations and definitions that are needed at compile time. For nontemplate interfaces, you must supply the header files that declare your classes, functions, and global data. For template interfaces, you must provide your template declaration files as well as your template definition files.

For more information on creating libraries, see the ar(1) reference page and the loader(1) reference page.


Previous Next Contents Index
  

1.800.AT.COMPAQ

privacy and legal statement