5.1. How do I port my 16 bit app to 32 bits?
Trying to compile your program with a 32 bit compiler
is usually the first big step: fix all the errors it shows and then see
if it
works when it is run. A raw API app can just be rebuilt,
using PORTTOOL.EXE to help you. Using the "windowsx.h" macros
and message crackers can assist you here. Class libraries
often provide the message cracking for you, so make life a bit easier.
MFC Apps can be ported fairly quickly by opening up the
project in Visual C++ and rebuilding. For OWL apps, just create a
new 32 bit target or a new project with a 32 bit exe
as the destination.
You may be disappointed to find little or no performance
improvement, or even worse a slowdown. The latter is most likely on
Windows 95, where a lot of the OS is still 16 bits wide.
The real speedup of win32 comes with higher power processors, and
Windows NT. The new features of Win32 will still benefit
application son Win95, and with some extra programming (threads
& async IO) performance can be significantly improved.
5.2. Common Pitfalls in porting from 16 to 32 bits
Integers are bigger. This can
break IPC and reading old files.
Fix: For legacy structures redefine
int references to short
Structure alignment has changed.
Causes the same problems as above.
Fix: return packing to BYTE
alignment for these structures. The include files "pushpack1.h" and "poppack.h"
can be
used around these structure
to fix them.
0xffff is no longer equivalent
to (UINT)-1. Use the macros in "limits.h"
No DIB.DRV. Use CreateDIBSection()
to create a DIB which you can apply GDI calls to, and use BitBlt() to draw
it
afterwards.
A changed comms API. Some thing
like DCBs remain, but comms ports are just another type of file now, with
blocking
I/O being the easiest way to
wait for input.
Long file names. Make sure that
MAX_PATH is used to declare all string that can hold a path, and do not
assume that
file names have an 8.3 format.
The implementation of Unicode
or ANSI in the Win32 API is assisted by lots of macros to bind to different
actual
functions. For example TextOut
is a macro mapping to TextOutA()or TextOutW(). This can cause problems
in C++
when you have a member function
whose name matches a windows API function as the macro renames it.
No VBX support. Actually Borland
4.5 manages this with a mixture of thunking (Win32s, win95) and inter-app
message
redirection (NT3.5 onwards)
.
Fix: Use OCXs instead. C++ users
will need BC5.0 or VCC4.0 to use these.
Passing handles to GDI &
memory objects between applications in PostMessage calls. System objects
must be
duplicated using DuplicateHandle().
Memory can only be exchanged via shared memory or WM_COPYDATA
messages.
Calling DOS and other interrupts
direct. You will probably find an API substitute somewhere in all the documentation,
but BIOS calls are pretty much
off-limits.
5.3. How do I read/write the serial port?
Win16 used to have lots of special functions such as ReadComm()
and WriteComm() to do this, but in win32 you just open a
serial port like any other file:-
//open COM1 for read and write
hPort=CreateFile( "COM1", GENERIC_READ | GENERIC_WRITE,
0, NULL,OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL );
Standard ReadFile() and WriteFile() functions can then
be used to read or write to the port. To set the port up reliably,
COMM port specific functions need to be used, so look
up the online help for details on the following functions:-
GetCommModemStatus(), SetCommState(), SetCommMask(),
SetupComm(), PurgeComm(), ClearCommError(),
SetCommTimeouts()
Tips:-
1.Even on win95, you can use overlapped IO
with a com port
2.The Signalled state of a port seems to
indicates it is ready for reading or writing, even if you only opened the
port
unidirectionally.
[Top of Section] [Index]
5.4. How do I read/write the parallel port?
Open it as per a serial port, using "LPT1" or "LPT2" as
the port name. This works provided the device which you are talking to
uses the standard ECP/EPP protocols. If you are trying
to use the parallel port as a non standard IO port, then you have to
access the port using port IO instructions -something
you are not meant to do from a user mode application.
[Top of Section] [Index]
5.5. How can two programs communicate now they have separate memory spaces?
SendMessage & PostMessage
Only works for the data which
can be fitted in to the two 32 bit parameters WPARAM and LPARAM, unless
you can
pass a pointer to shared memory.
WM_COPYDATA.
Easy, good for small quantities
of data. Works between 16 & 32 bit programs. NB: you need to manually
add it to your
16 bit header files.
OLE Automation.
Fairly easy but restricts you
to automation data types and is not as fast as other methods.
Use OLE2/COM IPC
Fast but requires interface
declarations and the MIDL compiler.
Memory mapped files
Only for 32:32 IPC. Needs some
synchronisation mechanism/objects too.
Named Pipes
Distributable, but you can't
create the server side on win95.
[Top of Section] [Index]
5.6. How can two programs communicate across a network?
There are lots of ways to do this: the most popular are probably sockets and DCOM.
WINSOCK
Powerful & cross platform,
but often a bit low level. Winsock 2 provides more protocol independence
so socket apps
can run over IPX, IP and other
protocols. Beware of byte ordering and structure packing issues when talking
to
non-Win32 platforms.
OLE Automation.
Only possible with VB4 enterprise
edition at present.
Distributed COM
This is built into NT4 and available
as an update for Win95 -and with all IE4 upgrades
DCE/Microsoft RPC
You need the win32 SDK to use
this.
Named Pipes
Note that you can't create the
server side on win95.
Mailslots
When broadcasting a message
to all clients in a workgroup, the message is sent over every transport:
clients may
therefore receive multiple copies.
Design your protocol to handle this.
Using an email system such as
Exchange as the transport.
[Top of Section] [Index]
5.7. How can I tell what version of windows I'm running?
With the function GetVersionEx().
[Top of Section] [Index]
5.8. How do I write a screen saver?
You look in the on line help: "Screen Savers", or in the
example code which your compiler ships with for a sample saver. The
main points to know are
1.a saver is just an executable with a .scr
extension
2.the setup dialog is invoked with a /c
argument; otherwise the app just shows the saver.
3.when invoked with "/p hwnd" then it's
preview mode
The best documentation and example code is at the Win95
Screensaver programming home page.
[Top of Section] [Index]
5.9. How do applications start up in the same place they were before windows shut down in windows 95?
Add a string value to the registry below HKEY_CURRENT_USER\Software\Windows\CurrentVersion\RunOnce
and also save your window state when you handle WM_ENDSESSION,
reloading your state on startup.
[Top of Section] [Index]
5.10. How do you do those pop-up menus on the right mouse button?
Traditionally this was done with a handler for WM_RBUTTONDOWN
[or UP] which mapped the client co-ordinates to the
screen and then called TrackPopupMenu() passing the handle
of a pop-up menu which you have created. In win95/NT3.51
onwards, you can opt to handle the message WM_CONTEXTMENU.
This is generated by the system if the
WM_RBUTTON* messages are not handled by the app. This
has two advantages
the co-ordinates are translated
for you so that x = HIWORD(lParam), and y = LOWORD(lParam)
It works with that new button
on Microsoft natural and other windows keyboards.
[Top of Section] [Index]
5.11. How do I access hardware via IO ports or mapped memory?
You can get away with port IO in user level code on Windows
95 & 98 through assembly language instructions like "__asm in
al,dx" and "_asm out dx,al" . The VC5 header file
you aren't supposed to.
For NT, or serious device access in win95, you'll need
a device driver. Have a look at the device driver FAQ , or some of the
driver programming groups -none of which have the word
driver in their title to improve the signal to noise ratio. (key words:
VxD and kernel mode)
The NT DDK samples you need to look at are DDK\SRC\GENERAL\{MAPMEM, PORTIO}
Doctor Dobbs Journal in May 96 had an article called DirectIO
which showed how to add a device driver to tweak the NT
task protection masks so that in and out instructions
are allowed in user mode code. This is an invaluable trick for non
commercial & prototype applications, but not really
acceptable for shipping products. NT separates device drivers from user
code for valid reasons: performance, reliability on multi-processor
systems and to enable applications to be more portable.
There are a pair of low cost shareware device drivers
which claim to support device IO and interrupts from user mode code.
The commercial product WinRT from Blue Water Systems
can do this and more.
[Top of Section] [Index]
5.12. How do I handle interrupts in my windows 32 program?
Usually you have to write a device driver or VxD. Writing
device drivers is not as hard as it sounds -especially WDM drivers.
It just needs extra learning and a more complex debugging
setup. Otherwise, follow up some of the URLS in the previous
section to see if their products meet your needs.
Some device drivers (such as the standard serial port
driver) can set Event objects in response to external state changes (r.e.
some of the RS232 lines) These can be used by normal
applications.
[Top of Section] [Index]
5.13. Can I use Win9x, NT or CE as a real time OS?
Not as far as the authors of the comp.realtime FAQ are
concerned. The lack of priority inheritance can make priority inversion
deadlocks possible, and there are not enough process
and thread priorities for their scheduling needs.
Win9x should certainly be avoided for time critical code
-unless you want to write assembler routines in VxDs, which is the
only reliable way to do so.
Windows NT can be used more easily for "soft real time"
applications; it's interrupt handling architecture (interrupt handlers
should just schedule deferred procedure calls) make hard
real time tasks (such as soft modems) very hard to implement
reliably.
WDM is emerging as a single driver model for new bus (1394,
USB) drivers on both platforms. The related video handling
driver architecture "WDM Streaming" could be useful not
just for time critical video processing, but also as a way of gluing
together other bigh bandwdith kernel mode data sources
and sinks.
Windows CE has some potential as a lighter weight alternative.
However there is a fundamental problem in the Win32 system
architecture: applications and device drivers are cleanly
split. This is great for hardware independent applications, and
application independent hardware, but not so good for
anyone trying to write a custom application coupled directly to a piece
of non standard hardware. That's what DOSDR-DOS, and
RTOS products like QNX and VxWorks are for. There are stated
plans for CE to evolve to become a hard RTOS, but as
this platform's evolution seems to follow the needs of high visibility
product categories (WebTV, HP/C & others), it is
hard to predict when CE will reach this state -if indeed it ever does.
Neither Win9x or NT are very good for time critical user
mode code. Win9x, lacking a re-entrant Win16 subsystem, cannot be
used very determinstically. (I.e. you cant predict whether
or not you thread gets locked out from an API call). NT does have
real time priority process and threads, which can be
used to get as close to real time as you can hope to do with Windows.
[Top of Section] [Index]
5.14. How do I do system wide keyboard and mouse hooks?
You need to put the hooks into a DLL which is then mapped
into the address space of all applications.
[Top of Section] [Index]
5.15. How do I get SetCapture to work the way it did I Win31?
In 32 bit windows SetCapture only captures the mouse for
the current input thread. However, if you set a journalling hook the
system input queue will be serialised and you can magically
call SetCapture() to grab the mouse regardless of it's on screen
position. See [MSJ April 1995 v10#4].
[Top of Section] [Index]
5.16. How do I get my program to start even if a user is not logged on?
NT: Make it a service.
Win95: add it to the list of registered apps under HKCU\Software\Windows\CurrentVersion\RunOnce
[Top of Section] [Index]
5.17. How do I load/display a 256 color bitmap using LoadBitmap (or CBitmap)?
You can't, it throws away the palette. Use {Find, Lock,
Load}Resource() to load a device independent bitmap (DIB) instead.
Or example code:
Borland's TDib class
The example MFC DIB classes
in "Animation in Win32", Inside Visual C++, or some MSJ articles by Paul
di Lascia
Use Microsoft's DIBAPI32.DLL
Use IMGLIB.DLL. This is a $50
library which can read and halftone bitmaps, JPEG, TIFF and PCD files into
DIB
memory blocks.
Stingray Software's MFC extension
classes.
The function LoadImage() can
also load deep color images.
You will also have to learn about palettes and their management.
"Animation in Win32" has some good explanations of this.
[Top of Section] [Index]
5.18. How can my 32 bit program call a 16 bit library?
NT: You can't do this directly. You will have to write
a 16 bit stub app which forwards commands and responses via some
IPC mechanism such as COM.
Win9x: Use flat thunks. The thunk compiler is in the SDK, and the documentation is in the Programmer's guide to win95.
Win32s: Generic Thunks
[Top of Section] [Index]
5.19. How do I play a sound?
With PlaySound, MessageBeep or the low level waveOut calls.
You will probably need to link in the multimedia libraries too.
(add WINMM.LIB to your project). The games sound API,
DirectSound, permits advanced techniques: mixing, 3D
positioning of sources and provides low latency access
to the sound buffers.
[Top of Section] [Index]
5.20. How do I play multiple sounds?
You have to use the DirectSound API to do this.
[Top of Section] [Index]
5.21. What is the file format of .{exe, ico, bmp, ttf, wav, avi,doc,xls, ...etc} files?
Common file formats are documented on the MSDN disks.
TrueType fonts are documented somewhere on Microsoft's ftp site
and are more complicated than you'd think.
The best on line site for file formats is Wotsit
[Top of Section] [Index]
5.22. How do I patch API entry points?
Unlike the Win16 world, you are not allowed to patch the
API calls for all applications by editing USER, KERNEL and GDI.
However, patching the API calls a single app makes is
easier in Win32 than Win16: you just modify the jump table at then end
of the application. To modify all applications' entry
points you need to apply the same technique but also inject your DLL into
each ones' address space.
Consult [MSJ Dec 1994 v9#12], and Richter's Advanced Windows.
[Top of Section] [Index]
5.23. How do I translate the value returned by GetLastError() into a string?
With FormatMessage(), asking for the system message tables.
This is a good i18n technique, as the OS can return translated
strings itself. NB: does not work in CE.
BOOL GetFormattedError(LPTSTR dest,int size)
{
DWORD dwLastError=GetLastError();
if(!dwLastError)
return 0;
BYTE width=0;
DWORD flags;
flags
= FORMAT_MESSAGE_MAX_WIDTH_MASK &width;
flags |= FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS;
return 0 !=
FormatMessage(flags,
NULL,
dwLastError,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
dest,
size,
NULL);
}
[Top of Section] [Index]
5.24. Why are all my Exe files so big?
Either you have all the debug and browse info included
in it, or you have statically linked to MFC/OWL instead of using the
DLL versions.
[Top of Section] [Index]
5.25. Why do I get Undefined External errors when linking?
You have either not added the appropriate library to match
a newly added header file to your project, or there is some
case/name mangling problem.
WINMM.LIB is required for all
the multimedia functions (like PlaySound)
WSOCK32.LIB is required for
windows sockets
Remember to put extern "C" {}
around all C declarations imported around C++
[Top of Section] [Index]
5.26. How do I create a link to a file?
The only equivalent of a symbolic link is the "shortcut"
file, which is like a symlink except bigger, containing an icon and enough
information about the destination to be able to look
for it if it moves. -or even on other machines. These are documented in
the
MSDN disks, and a COM API exists to create and manipulate
them. Hard links can be created on NTFS disks by using the
backup API.
NT5 appears to extend linking significantly, with files
referable by their ObjectID, rather than just absolute or relative paths,
the
OS then doing the work of finding the file's location.
This will only work on NTFS drives, however.
[Top of Section] [Index]
5.27. How do I create/use Shortcuts (.lnk files)?
You have to use IShellLink to manipulate these. To invoke
the shortcut, use ShellExecuteEx(): ShellExecute does not work on
all link types -e.g. dial up networking links.
[Top of Section] [Index]
5.28. How many threads can a program have?
Each thread takes up space in the operating system, so
the number of threads a system will support is memory-bound and so
varies from machine to machine. Often a bit of re-engineering
-the use of IO Completion ports- can be used to reduce the
thread count a service will require.
A NT4 (service patch 3) and NT5 support "fibers" which
are threads scheduled by the applications themselves. These are
possibly lighter weight than standard threads, but seem
so rarely used that the limits have never been explored.
[Top of Section] [Index]
5.29. What are shell extensions?
These are in-process COM objects which implement a sparsely
documented set of interfaces (see MSDN/MSDN on the web)
and enable anyone to write their own "folder" within
the Windows Explorer shell
[Top of Section] [Index]
5.30. How do I get the shell to automatically create new documents of my type?
By adding a shellNew handler. The default is to get the
shell to create a zero length file of the appropriate name. Your
application's file loading code must handle this case
and treat it as creating a new blank but named file, instead of as an error.
Note that although this is a Win95 integration guideline,
it is now often considered good form to ask the user if they actually
want you to extend their shell in this way -as once you
have 20+ applications installed, that pop up menu ceases to be too
useful.
[Top of Section] [Index]
5.31. Why doesn't my app have nice 16x16 and 48x48 icons? (aka: Why does my app still have the MFC icon?)
Because you haven't written any. Use your icon editor
to create new device images of the appropriate size within each existing
icon. Then update your windows by using either RegisterClassEx
or WM_SETICON. The latter is a message which can be
posted to any window to get it to change its icons and
is very useful for dialogs and other situations where the class is registered
out of your control.
When the MFC App wizard is used to generate an application,
it generated 16x16 and 32x32 icons: you need to modify both
when customising your program.
[Top of Section] [Index]
5.32. How do I hide my window from the task bar?
A window will show up in the taskbar button area if
1.The window is visible
2.The window is not a child window.
3.The window is not owned.
4.The window is not a tool window.
There are some exceptions to the above rules, but they
apply only to legacy ("designed for Windows 3.1 or earlier")
applications.
[Top of Section] [Index]
5.33. How I give my application a tray icon? (one of those little icons at the end of the start bar)
Look in the manuals for the Shell_NotifyIcon() API call. This lets you add new Icons to the tray
MSJ March 1995 has a good article covering the whole subject,
although sadly it is no longer in the MSJ section of MSDN.
Otherwise see "Adding and Deleting Taskbar Icons" in
MSDN or the "Programming the Win95 User Interface" .
[Top of Section] [Index]
5.34. How do I get Internet Explorer/Office 97 menus & toolbars?
You can do these with the Rebar/Coolbar common control,
available from the COMMCTRL.DLL library distributed with IE3
and IE4. Documentation for using this control comes with
the Internet SDK, and VC++ preview for IE4.
Note that once you use this control, you end up in a complex
situation regarding redistribution: you have to redistribute a
common controls update One strategy here is to design
an application which only uses the rebar if the library is up to date,
and
drop to the previous version if not.
[Top of Section] [Index]
5.35. How do I measure Time in my program?
There are lots of ways of measuring time, each with their
own advantages and disadvantages. Variables are accuracy,
portability, overhead and ease of use.
time()
class SetHT
: public Set {
`new SetHT(...)' returns a `SetHT*', so `*new' returns
a SetHT&. A SetHT is-a
Clients can use this as if they were `virtual constructors':
This fn will work correctly regardless of how the Set
is implemented (hash
See above on `separation of interface from implementation'
for more.
Q106: How can I call a C function `f()' from C++ code?
Q107: How can I create a C++ function `f()' that is callable
by my C code?
Caveats and implementation dependencies:
Q109: How can I pass an object of a C++ class to/from
a C function?
/****** C/C++
header file: X.h ******/
#ifdef __STDC__
#ifdef __cplusplus
#ifdef __cplusplus
Then, in file `X.C':
In C++ file `main.C':
Finally, in a C file `c-fn.c':
Passing ptrs to C++ objects to/from C fns will FAIL if
you pass and get back
Q110: Can my C function access data in an object of a
C++ class?
(First read the previous question on passing C++ objects
to/from C functions.)
If the C++ class has any base classes at all (or if any
fully contained
Furthermore you can often (but less than always) assume
a `void*' appears in
If the class has any virtual base classes, it is more
complicated and less
ART 17
Q112: What is the type of `ptr-to-member-fn'? Is
it diffn't from `ptr-to-fn'?
Q113: How can I ensure `X's objects are only created with
new, not on the stack?
class X {
//only want to allow dynamicly allocated X's
X* Xptr = X::create(5);
Q114: How do I pass a ptr to member fn to a signal handler,X
event callback,etc?
As a patch for existing software, use a free function
as a wrapper which takes
Ex: suppose you want to call X::memfn() on interrupt:
class X {
//wrapper fn remembers the object on
which to invoke memfn in a static var:
main()
Q115: Why am I having trouble taking the address of a
C++ function?
Long ans: In C++, member fns have an implicit parameter
which points to the
Q116: How do I declare an array of pointers to member
functions?
class Frob
{
Rettype (Frob::*fn_ptr[3])(T1,T2)
= { &Frob::f, &Frob::g, &Frob::h };
You can make the array declaration somewhat clearer with
a typedef:
To call one of the functions on an object `frob', use:
You can make the call somewhat clearer using a #define:
PART 18
Q117: How can I insert/access/change elements from a linked
list/hashtable/etc?
This answer will be a lot to swallow for novice C++'ers,
so I'll give a couple
[1] Empower the List with a `viewport' or `cursor' that
references an arbitrary
[2] Provide a separate class called ListIter. ListIter
has member fns named
The reason option [2] is better becomes apparent when
you use classes that only
Note that the options are not mutually exclusive; it is
possible to provide
[3] The third possibility considers the entire iteration
as an atomic event. A
Q118: What's the idea behind `templates'?
The questions about templates are in the `Containers'
section since templates
Q119: What's the syntax / semantics for a `function template'?
void swap(int&
x, int& y)
If we also had to swap floats, longs, Strings, Sets, and
FileSystems, we'd get
template
Every time we used `swap()' with a given pair of types,
the compiler will go to
main()
(note: a `template function' is the instantiation of a
`function template').
Q120: What's the syntax / semantics for a `class template'?
//this would
go into a header file such as `Vec.h':
Just as with `swap()' above, repeating the above over
and over for Vec of
//this would
go into a header file such as `Vec.h':
Unlike template functions, template classes (instantiations
of class templates)
main()
Q121: What is a `parameterized type'?
Q122: What is `genericity'?
Q123: How can I fake templates if I don't have a compiler
that supports them?
Here's how you'd declare my `Vec' example from above.
First we define `Vec(T)'
#include
//to get the `name2()' macro
Next we declare the class Vec(T) using the name `Vecdeclare(T)'
(in general you
#define Vecdeclare(T)
\
Note how each occurrence of `Vec' has the `(T)' postfixed.
Finally we set up
//strangely
enough this can also go into Vec.h
When you wish to use a Vec-of-String and Vec-of-int, you
would say:
#include "Vec.h"
//pulls in too; see below...
In exactly one source file in the system, you must provide
implementations for
#include "Vec.h"
Note that types whose names are other than a single identifier
do not work
#include "Vec.h"
It is important that every declaration of what amounts
to `Vec' must all
PART 20
Miscellaneous technical issues:
Q131: Why are classes with static data members getting
linker errors?
The usual place to define static member variables of class
`X' is file `X.C'
Q132: What's the difference between the keywords struct
and class?
Q133: Why can't I overload a function by its return type?
Ex: the compiler says the following two are an error:
A: Return types are not considered when determining unique
signatures for
main()
Q134: What is `persistence'? What is a `persistent
object'?
The challenge with persistent objects is to effectively
store their method
Miscellaneous environmental issues:
Q135: Is there a TeX or LaTeX macro that fixes the spacing
on `C++'?
\def\CC{C\raise.22ex\hbox{{\footnotesize +}}\raise.22ex\hbox{\footnotesize
+}}
\def\CC{{C\hspace{-.05em}\raisebox{.4ex}{\tiny\bf ++}}}
Q136: Where can I access C++2LaTeX, a LaTeX pretty printer
for C++ source?
Host aix370.rrz.uni-koeln.de (134.95.80.1)
Last updated 15:41 26 Apr 1991
Q137: Where can I access `tgrind', a pretty printer for
C++/C/etc source?
`tgrind' usually comes with the public distribution of
TeX and LaTeX. Look in
A more up-to-date version of tgrind by Jerry Leichter
can be found on:
Q138: Is there a C++-mode for GNU emacs? If so,
where can I get it?
c++-mode-2 (1.0) 87-12-08
Another C++ major mode.
C++ major mode.
c-support (46) 89-11-04
Q139: What is `InterViews'?
Q140: Where can I get OS-specific questions answered (ex:BC++,DOS,Windows,etc)?
You can subscribe to the BC++ mailing list by sending
email to:
The BC++ bug report is available via anonymous ftp from
sun.soe.clarkson.edu
Relevant email addresses:
Q141: Why does my DOS C++ program says `Sorry: floating
point code not linked'?
You can fix it by (1) using instead of , or (2)
by
See question on stream I/O for more reasons to use
vs .
Q18: What are inline fns? What are their advantages? How
are they declared?
Beware that overuse of inline functions can cause code
bloat, which can in
They are declared by using the `inline' keyword when the
function is defined:
Generally speaking, a function cannot be defined as `inline'
after it has been
part of ANSI standard C, found
in time.h and measuring seconds since 1/Jan/1970. Works reliably until
January 2038.
Portable, and good for both
external displaying (via ctime()) and for arithmetic. Also integrates well
with time zone
settings. Not useful for dates
before 1970.
GetTickCount()
Returns elapsed CPU tick count
to nominally millisecond resolution. On Win95, each tick is 55mS, on WinNT
it is
usually a smaller value (such
as 10-20mS). Wraps every couple of months, and bears little relation to
the outside
world. Also, laptops and OnNow
PCs may suspend the timer while in some sleep states.
GetSystemTime
Returns system time in a fairly
complex SYSTEMTIME structure. Converting it to a FILETIME format makes
comparisons and differences
easier. The resolution is probably no better than that of the GetTickCount()
call.
QueryPerformanceCounter()
A higher resolution counter,
whose frequency and accuracy varies from OS to OS, and from CPU to CPU.
You need to
use QueryPerformanceFrequency()
to discover the frequency. On a single processor NT platform the counter
frequency
is 1+ MHz, so is accurate to
microseconds. On a multiprocessor system it uses the RDTSC opcode to measure
CPU
clock ticks. Good for low level
performance measurement, although the switch to kernel mode adds enough
overhead to
hamper profiling of small routines.
x86 assembler: rdtsc
The "Read Time Stamp Counter"
instruFONT>
class Set
{ //normally this would be a template
public:
virtual void insert(int); //Set of `int'
virtual int remove();
//...
virtual Set& clone() const = 0;
//pure virtual; Set is an ABC
virtual Set& fresh() const = 0;
virtual ~Set() { } //see on `virtual destructors' for
more
};
//a hash table in here
public:
//...
Set& clone() const { return *new SetHT(*this); }
Set& fresh() const { return *new SetHT(); }
};
Set, so the return value is correct. The invocation
of `SetHT(*this)' is that
of copy construction (`*this' has type `SetHT&').
Although `clone()' returns a
new SetHT, the caller of clone() merely knows he has
a Set, not a SetHT (which
is desirable in the case of wanting a `virtual ctor').
`fresh()' is similar,
but it constructs an `empty' SetHT.
void client_code(Set&
s)
{
Set& s2 = s.clone();
Set& s3 = s.fresh();
//...
delete &s2; //relies on destructor being virtual!!
delete &s3; // ditto
}
table based, AVL tree based, etc).
A: Tell the C++ compiler that it is a C function:
extern "C" void f();
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.
* your `main()' should be compiled with your C++ compiler.
* your C++ compiler should direct the linking process.
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):
#ifdef __cplusplus
/*`__cplusplus' is #defined iff compiler is C++*/
extern "C" {
#endif
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
}
#endif
class X {
int a;
public:
X();
void frob(int);
};
#endif
//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;
}
#include "X.h"
int main()
{
X x;
c_fn(&x);
return 0;
}
/* C source
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();
}
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).
A: Sometimes.
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
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.
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).
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.
A: A member fn of class X has type: Returntype
(X::*)(Argtypes)
while a plain function has type: Returntype
(*) (Argtypes)
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:
protected:
X();
X(int i);
X(const X& x);
virtual ~X();
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); }
};
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).
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).
public:
void memfn();
static void staticmemfn();
//a static member fn can handle it
//...
};
static X* object_which_will_handle_signal;
void X_memfn_wrapper() { object_which_will_handle_signal.memfn();
}
{
/* signal(SIGINT, X::memfn);
*/ //Can NOT do this
signal(SIGINT, X_memfn_wrapper);
//Ok
signal(SIGINT, X::staticmemfn);
//Also Ok
}
Short ans: Please read previous question first; this
is a corollary.
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.
A: Use the following declaration:
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);
//...
};
typedef
Rettype (Frob::*Frob_member_ptr)(T1,T2);
//...
Frob_member_ptr
fn_ptr[3] = { &Frob::f, &Frob::g, &Frob::h };
Frob frob;
//...
(frob.*fn_ptr[i])(x,
y);
#define
apply_member_fn(object,fn) ((object).*(fn))
//...
apply_member_fn(frob,fn_ptr[i])(x,
y)
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.
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.
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.
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).
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.
both [2] *and* [1], giving rise to the notion of a `primary'
list position,
with instances of ListIter being somewhat secondary.
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).
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.
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.
A: Consider this function that swaps its two integer
arguments:
{
int tmp = x;
x = y;
y = tmp;
}
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:
void swap(T&
x, T& y)
{
T tmp = x;
x = y;
y = tmp;
}
the above definition and will create yet another `template
function' as an
instantiation of the above. Ex:
{
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'
}
A: Consider this container class of that acts like an
array of integers:
class Vec
{
int xlen;
int* xdata;
int check(int i); //return i if i>=0 && i= xlen) throw
BoundsViol("Vec", i, xlen);
return i;
}
float, char, String, Vec, Vec-of-Vec-of-Vec, etc, will
become tedious. Hence
we create a single class template:
template
class Vec
{
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;
}
need to be explicit about the parameters over which they
are instantiating:
{
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
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.
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.
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.
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:
#define
Vec(T) name2(Vec,T)
would postfix the name of the class with `declare', such
as `Listdeclare' etc):
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; } \
};
another macro that `implements' the non-inline member
function(s) of Vec:
#define Vecimplement(T)
\
int Vec(T)::check(int
i)
\
{
\
if (i < 0 || i >= xlen) throw BoundsViol("Vec", i, xlen);
\
return i;
\
}
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;
the non-inlined member functions:
declare
(Vec,String) declare (Vec,int) declare
(Vec,float)
implement(Vec,String)
implement(Vec,int) implement(Vec,float)
properly. Ex: Vec(char*) creates a class whose
name is `Vecchar*'. The patch
is to create a typedef for the appropriate type:
typedef char*
charP;
declare(Vec,charP)
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.
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
(or X.cpp, X.cc, X.c++, X.c or X.cxx; see question on
file naming conventions).
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.
char
f(int i);
float f(int
i);
overloading functions; only the number and type of parameters
are considered.
Reason: which function should be called if the return
value is ignored? Ex:
{
f(3); //which should be invoked??
}
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.
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.
A: Yes, here are two:
A: Here are a few ftp locations:
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
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).
the directory:
...tex82/contrib/van/tgrind
venus.ycc.yale.edu
in [.TGRIND]
A: Yes, there is a C++-mode for GNU emacs. You
can get it via:
Bruce Eckel,Thomas Keffer,
archive.cis.ohio-state.edu:/pub/gnu/emacs/elisp-archive/as-is/c++-mode-2.el.Z
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++
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
Lynn Slater,
archive.cis.ohio-state.edu:/pub/gnu/emacs/elisp-archive/misc/c-support.el.Z
Partial support for team C/C++
development.
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.
A: see comp.os.msdos.programmer, BC++ and Zortech mailing
lists, BC++ and
Zortech bug lists, comp.windows.ms.programmer,
comp.unix.programmer, etc.
| 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
[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).
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
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.
including the following function definition somewhere
in your compilation (but
don't call it!):
static void
dummyfloat(float *x) { float y; dummyfloat(&y); }
A: An inline function is a function which gets textually
inserted by the
compiler, much like a macro. Like macros, performance
is improved by avoiding
the overhead of the call itself, and (especially!) by
the compiler being able
to optimize *through* the call (`procedural integration').
Unlike macros,
arguments to inline fns are always evaluated exactly
once, so the `call' is
semantically like a regular function call only faster.
Also unlike macros,
argument types are checked and necessary conversions
are performed correctly.
turn have a negative performance impact in paging environments.
inline void
f(int i, char c) { /*...*/ } //an inline function
or by including the function definition itself within
a class:
class X {
public:
void f(int i, char c) { /*...*/ } //inline function within
a class
};
or by defining the member function as `inline' outside
the class:
class X {
public:
void f(int i, char c);
};
//...
inline void
X::f(int i, char c) {/*...*/} //inline fn outside the class
called. Inline functions should be defined in a
header file, with `outlined'
functions appearing in a `.C' file (or .cpp, etc; see
question on file naming
conventions).