2005/09/14 | Turbo C++ for Windows: ANSWERS TO COMMON QUESTIONS
类别(语言类学习笔记) | 评论(0) | 阅读(722) | 发表于 23:22
Turbo C++ for Windows: ANSWERS TO COMMON QUESTIONS


G e t t i n g S t a r t e d
----------------------------------------------------------------------
Q. How do I install Turbo C++?
A. Run the INSTALL program from DISK 1. To start the installation,
change your current drive to the one that has the install program
on it and type WIN INSTALL. For example, if you will be installing
from drive A:, type:

A:
WIN INSTALL

At this point, the INSTALL program will appear with menu selections
and descriptions to guide you through the installation process.

Q. How do I run Turbo C++?
A. After you have installed Turbo C++, type "WIN TCW" from the DOS
prompt and you're ready to go. Be sure that you've modified your
DOS path, adding the directory that tcw.exe is located in.

C o m m o n C + + Q u e s t i o n s
----------------------------------------------------------
Q. When linking C or Assembly language modules with C++ modules I get
undefined symbol errors at link time. It appears that none of the C
or Assembly public symbols can be found.
A. C++ is a strongly typed language. In order to support the language
to its fullest, Turbo C++ must attach information to the symbols
generated for function names and variables. When this is done, the
symbol will no longer match the standard C style function name. In
order to link correctly, the compiler must be notified that the symbol
is declared in an external module without type information tacked on
to the symbol. This is done by prototyping the function as type
extern "C". Here is a quick example:
extern "C" int normal_c_func( float, int, char ); // name not altered
void cplusplus_function( int ); // name altered
See related comments on extern "C" in the Turbo C++ for Windows
Programmer's Guide, Chapter 2.

Q. Classes with static data members are getting linker errors ("undefined").
A. This code is built into Turbo C++ 1.0 (DOS) but not in Turbo C++ for
Windows. In the earlier implementation, static members without
definitions were given a default value of 0. This default definition
will no longer be made in TCW. The programmer must now give an explicit
definition for each static member.
Here is a quick example:
class A
{
     static int i;
};
A linker error saying that A::i is not defined will result unless the
source also contains a line such as:
int A::i = 1;

Q. What potential problems can arise from typecasting a base class pointer
into a derived class pointer so that the derived class's member functions
can be called?
A. Syntactically this is allowable. There is always the possibility of
a base pointer actually pointing to a base class. If this is
typecast to a derived type, the method being called may not exist
in the base class. Therefore, you would be grabbing the address of
a function that does not exist.

Q: What's the difference between the keywords STRUCT and CLASS?
A: The members of a STRUCT are PUBLIC by default, while in CLASS,
they default to PRIVATE. They are otherwise functionally equivalent.

Q: I have declared a derived class from a base class, but I can't access any
of the base class members with the derived class function.
A: Derived classes DO NOT get access to private members of a base class.
In order to access members of a base class, the base class members must
be declared as either public or protected. If they are public, then
any portion of the program can access them. If they are protected, they
are accessible by the class members, friends, and any derived classes.

Q: I have a class that is derived from three base classes. Can I insure that
one base class constructor will be called before all other constructors?
A: If you declare the base class as a virtual base class, its constructor
will be called before any non-virtual base class constructors. Otherwise
the constructors are called in left-to-right order on the declaration
line for the class.

Q: When debugging my program in Turbo Debugger, I notice that none of my
inline functions are expanded inline. Instead, they are all done as
function calls.
A: Whenever you compile your program with debugging information included,
no functions are expanded inline.

Q. In C++, given two variables of the same name, one local and one global,
how do I access the global instance within the local scope?
A. Use the scope (::) operator.

int x = 10;
for(int x=0; x < ::x; x++)
{
MessageBox(GetFocus(), "This will loop 10 times", "Note", MB_OK);
}

Q. Will the following two functions be overloaded by the compiler, or
will the compiler flag it as an error? Why?
void test( int x, double y); & int test( int a, double b);
A. The compiler will flag this as a redeclaration error because
neither return types nor argument names are considered when determining
unique signatures for overloading functions. Only number and type
of arguments are considered.

Q. If I pass a character to a function which only only accepts an int,
what will the compiler do? Will it flag it as an error?
A. No. The compiler will promote the char to an int and use the integer
representation in the function instead of the character itself.

Q. I was trying to allocate an array of function pointers using the new
operator but I keep getting declaration syntax errors using the following
syntax: new int(*[10])(); What's wrong?
A. The new operator is a unary operator and binds first to the int keyword
producing the following: (new int) (*[10])();
You need to put parentheses around the expression to produce the
expected results: new (int (*[10]());

Q. What are inline functions? What are their advantages? How are they
declared?
A. An inline function is a function which gets textually inserted by
the compiler, much like macros. The advantage is that execution time
is shortened because linker overhead is minimized. They are declared
by using the inline keyword when the function is declared:

inline void func(void)
{
MessageBox(GetFocus(), "within inline function func()",
"Note", MB_OK);
}

or by including the function declaration and code body within a class:

class test
{
public:
void func(void)
{
MessageBox(GetFocus(), "within inline function func()",
"Note", MB_OK);
}
};

Q. If I don't specify either public or private sections in a class,
what is the default?
A. In a class, all members are private by default if neither public nor
private sections are declared.

Q. What does the _seg modifier do?
A. Using _seg cause a pointer to become a storage place for a
segment value, rather than an offset ( or a segment/offset ).
For instance, if "int _seg *x" contains the value 0x40,
then when you use "*x", the value pointed to will be at
segment 0x40, offset 0. If you add a value to the pointer,
the value is multiplied by the size of the pointer type. That
new value is used as an offset, and is combined with the segment
value contained in the pointer. For instance,

int _seg *x;
int value;

x = (int _seg *)0x40;
value = *(x + 20);

value is assigned the value of the integer at 0x40:0x28
(Remember, 20 * sizeof(int) = 40 = 0x28).

You can find a more detailed description of _seg in the Turbo C++
for Windows Programmer's Guide, Chapter 6.

Q. How do I allocate arrays greater than 64K?
A. You must use dynamic allocation. The basic procedure is to use
GlobalAlloc to obtain the memory from Windows and then use a
fast huge pointer to index through the memory obtained from Windows.
The below code demonstrates the process. In addition, the size of the
data type that your huge pointer points to must be a power of 2 in
bytes (i.e. 16, 32, 64, etc).

// compile with fast huge pointers turned on

int PASCAL WinMain (HANDLE hInst, HANDLE hPrevInst,
LPSTR lpCmdLine, int nCmdShow)
{
long z;
HANDLE hMem;
long huge *array;

hMem = GlobalAlloc(GMEM_FIXED | GMEM_ZEROINIT, 100000L * sizeof(long));
array = (long huge *) GlobalLock(hMem);

for (z=0; z < 100000L; z++)
array[z] = z;

GlobalUnlock(hMem);
GlobalFree(hMem);

return 0;
}

Q. What is a friend member function?
A. Declaring a friend gives non-members of a class access to the
non-public members of a class.

Q. Why do I get a "Type name expected" error on my definition of a
friend class in my new class?
A You need to let the compiler know that the label you use for your
friend class is another class. If you do not want to define your
entire class, you can simply have "class xxx", where xxx is your
label.

Q. What is the "this" pointer?
A. "this" is a local variable in the body of a non-static member function.
It is a pointer to the object for which the function was invoked. It
cannot be used outside of a class member function body.

Q. Why does a binary member function only accept a single argument?
A. The first argument is defined implicitly.

Q: Looking through the class libraries there are definitions in classes
which look like:
class test {
int funct( void ) const;
};
What is the const keyword doing here?
A: There is a pointer to the object for which a function is called
known as the 'this' pointer. By default the type of 'this'
is X *const ( a constant pointer). The const keyword changes the
type to const X *const ( a constant pointer to constant data ).

Q: I want to use _new_handler and set_new_handler.
A: Turbo C++ supports _new_handler and set_new_handler. You can find
a discussion of them in Chapter 3 of the Turbo C++ for Windows
Programmer's Guide. The type of _new_handler is as follows.
typedef void (*vfp)(void);
vfp _new_handler;
vfp set_new_handler( vfp );

Q: I would like to use C++ fstreams on a file opened in binary mode,
how is this done?
A: Use ios::binary as the open mode for the file:
#include <fstream.h>
ifstream binfile;
binfile.open("myfile.bin", ios::binary);

Q: How can I get at the DOS file handle associated with my iostream?
A: Using a combination of member functions fd() and rdbuf() you can
get at the file handle.
#include <fstream.h>
#define fstrno(s) (((s).rdbuf())->fd())
ifstream test("test.txt");
int handle;
handle = fstrno(test);


C o m m o n W i n d o w s Q u e s t i o n s
----------------------------------------------------------------------
Q. Why isn't my DLL working correctly?
A. One possibility is that you are not linking in the correct 'cw'
library. If you are building a small model DLL, you should be using
cwc, not cws. If you are building a medium model DLL, you should
be using cwl, not cwm. Compact and large models should use cwc
and cwl respectively.

Q. I have a project that works fine using Borland C++ 2.0. When I use
Turbo C++ for Windows 3.0, the linker cannot find my
cwinX.lib file, where X corresponds to the memory model I am
using. What's wrong? A. Turbo C++ for Windows 3.0 uses
different library names than Borland C++ 2.0. Instead of
cwinX.lib, use cwX.lib in your project files, when using
Turbo C++ for Windows 3.0.

Q. Why isn't my program working correctly? I'm getting a message box from
Windows saying "Unrecoverable Application Error".
A. One possible answer is that the program was not built correctly.
For example, the linker did not get the correct information to export
functions. Diagnostic messages from the linker could indicate this.
To check that you have built your program on DLL as expected, review
the section in Chapter 9 of the Turbo C++ for Windows Programmer's
Guide that deals with exports. This section has a table with 8 columns
describing the possible combinations you might have used to build your
program. If the setup of your program corresponds to one of the last
three columns, chances are that your program was not built correctly
( or, at least, as you intended ). Column 5 corresponds to the 'classical'
method of building windows programs ( that is, all exports are declared
in the module definition file ( the .def file )).

The columns that use explicit exports will build 'better' code in sense
that the compiler will not make 'exportable' any functions that it does
not actually export. However, it is here that many people will run into
problems. If you have any functions declared as exports in the .def
file but the module is compiled with explicit exports, then you probably
have built the program incorrectly (the function will be exported only
if it is preceded by _export in the source code).

Q. How do I use the _export key word?
A. Put the "_export" immediately before the function name in the function
declaration to export that function.
Here is a quick example:
long FAR PASCAL _export func(void) {...}

Q. How do I format a long integer using wsprintf?
A. Use the "%ld" format:

char buffer[50];
long int l = 666L;
wsprintf(buffer, "%ld", l);

Q. How do I format a long double using wsprintf?
A. The Windows 3.0 function wsprintf doesn't support floating point
formats. You can use the "%Lf" format with sprintf, however. Be
sure to include the stdio.h header for sprintf().

char buffer[50];
long double ldbl = 1E666;
sprintf(buffer, "%Lf", ldbl);

Q. Can I use standard file handling functions such as fopen() in
a Windows application?
A. Yes. However, do not mix the "traditional" and Windows file handles
when calling functions. For example, do not pass a handle obtained
from OpenFile() to fread().

I n t e g r a t e d E n v i r o n m e n t
----------------------------------------------------------------------
Q. Why is Turbo C++ for Windows not able to find any of my #include files?
A. The compiler searches for include files in the Turbo C++ for
Windows Include Directories path. You can specify this path
through the Options|Directories menu. The INSTALL program
initially sets this path to the directory where it copied all
the Turbo C++ for Windows *.h files.

Q. Why do I get the message:
Linker Error: Unable to open input file 'C0x.OBJ'
A. The linker searches for Turbo C++ for Windows start-up and
library files in the Turbo C++ for Windows Library
Directories path. You can specify this path through the
Options|Directories menu. The INSTALL program initially sets
this path to the directory where it copied the start-up and
library files.

Q. How do I get Turbo C++ for Windows to link in my own
libraries or use multiple source files? A. Turbo C++'s
Project facility is designed to allow you to work with
multiple files.

Q. When I Make, Run, or Trace a program, Turbo C++ for Windows
sometimes goes through the compile and link process even when
the object files are up-to-date. A. Turbo C++'s MAKE logic
works solely on a file's date and time stamp. If one of your
source files is marked with a date that's sometime in the
future, the object files that are created from it will always
be older than the source file, and Turbo C++ for Windows will
always try to rebuild the file. You can fix this by using
TOUCH.COM to set the file to the current date and time. You
should also make sure that your system's date and time are
always properly set. TOUCH.COM is documented in the file
UTIL.DOC.

Q. How come my old Turbo C (DOS) project files don't work anymore?
A. Project files now contain much more information about a project now,
and hence are no longer stored in ASCII format. To create a project
file, select PROJECT from the main menu, and follow the menus. To
convert your old project files to the new format, use the supplied
utility file PRJCNVT.EXE (documented in UTIL.DOC).

Q. How can I convert my Turbo C 2.0 project files to the new
format?
A. There is a conversion utility in your Turbo C++ for Windows
BIN directory called PRJCNVT.EXE. This program will perform
the conversion.

Q. My right mouse button appears to do nothing. Can I change this so it
will set breakpoints?
A. Yes, under the menu for Options|Environment|Mouse there is a
dialog box for the right mouse button. You can change it to set
breakpoints, or to do many other things.

Q. When I try to load a new file after editing a file, the first
file remains on the screen. How do I close the first file?
A. Use Alt-F3 to close the current file. Also, use F6 to move
from one file to the next, if there is more than one file
open at a time.

Q. I'm doing a search and replace operation, and the editor prompts me for
each replacement. I've selected "Change All", but it still does it.
A. To disable the prompting, you must unselect the "Prompt on replace"
option on the left side of the dialog box.

Q. When I try to use the any of the pseudo registers, like _AX, I
get the error message "Undefined symbol '_AX' in function..."
when I compile. Why?
A. You are only allowed to use the pseudo registers in the Turbo C++
C++ and ANSI modes of the compiler. You can change this setting
in the Options|Compiler|Source menu.

Q. Since I don't have a mouse, can I still copy blocks of code
from one file to another?
A. Yes. You can mark the beginning and end of a block by moving
to the appropriate area and pressing Ctrl-K-B (mark beginning) and
Ctrl-K-K (mark end). You can then use the copy and paste commands
in the Edit menu.

Q. I get errors when compiling the windows.h header file. Why?
A. Be sure that you have "Turbo C++" selected as your keywords option.
This option can be toggled under Options | Compiler | Source.

L i n k e r E r r o r s
----------------------------------------------------------------------
Q. I am linking C functions with C++ functions. The linker reports that
all of my C functions are undefined. Why?
A. Linking C++ modules with C modules requires the use of a linkage
specification. Prototypes for C functions within C++ modules must
be in one of the following forms:

extern "C" declaration
extern "C" { declarations }

For example, if a C module contains functions
"char *SCopy(char*, char*);" and "void ClearScreen(void)", they
must be declared in a C++ module in one of the following ways:

extern "C" char *SCopy(char*, char*);
extern "C" void ClearScreen(void);

or

extern "C" {
char *SCopy(char*, char*)
void ClearScreen(void);
}

For further examples, see the standard header files. For additional
comment, see Common C++ Questions.

Q. Why do I get the message:
Linker Error: Unable to open input file 'C0x.OBJ'
A. See the "Integrated Environment" section above.

Q. What is a 'Fixup overflow'?
A. See the listing of TLINK error messages in the Turbo C++ for Windows
User's Guide.

Q. I am linking my own assembly language functions with Turbo
C++ for Windows. The linker reports that all of my functions
are undefined. A. Make sure that you have put an underbar
character '_' in front of all assembly language function
names to be called by Turbo C++ for Windows. Your assembly
language program should be assembled with Case Sensitivity.
If compiling as C++ (rather than C), see "Common C++
Questions" above which discusses use of extern "C".

Q. I'm porting an application that uses communal variables to C++.
I've set up the compiler to recognize them, but I still get linker
errors:

Error: <name> defined in module <a> is duplicated in module <b>

A. C++ doesn't support explicit COMDEFs; you must use static
variables or switch to C.

Q. I get the linker warning "Attempt to export non-public symbol XXX"
where XXX is a function I am exporting in my .DEF file.
A. This indicates that there is a function exported in your DEF file which
was not found in your program by the linker. This warning should not
be ignored since in many cases attempting to export a non-existant
symbol implies that you may have missed exporting a symbol which DOES
exist. It may be that you have misspelled the name of your function
either in your source or in the EXPORTS section of your .DEF file.

It also may be that you are compiling your program (accidentally or
intentionally) as C++ code without taking into account the name-mangled
(encoded) identifiers employed for C++ compiling. If the program
is to be compiled as C++, the _export modifier should be used for
any functions to be exported. Remember that you should use _export
both in the function prototype and in the function definition.
The function entries in the EXPORTS section of the DEF file can then
be removed. Following this method, the declaration for a sample
exported function would be:

long FAR PASCAL _export WndProc (HWND, WORD, WORD, LONG) ;

An alternative way to export the functions would be to leave the EXPORTS
entry in the DEF file as-is and declare the function as extern "C" in the
C++ source code. This will "turn off" name-mangling for that function and
thus the identifier for that function will match the one exported in the
DEF file. Following this method, the declaration for a sample exported
function would be:

extern "C" long FAR PASCAL WndProc (HWND, WORD, WORD, LONG) ;

See related comments on extern "C" in the Turbo C++ for
Windows Programmer's Guide, Chapter 2.


O t h e r Q u e s t i o n s
----------------------------------------------------------------------
Q. I get a "floating point formats not linked" message when I run
my program. What can I do about it?

A. Floating point formats (for scanf() and related functions) are
not always linked, for savings in executable size. To force their
inclusion, put the following somewhere in your source files:

#pragma extref _floatconvert

Q. How do I change the stack size?
A. In your module definition file (.DEF file) you can set the size of
your stack by using the STACKSIZE statement. For example,
"STACKSIZE 6144" would set your stack size to 6,144 bytes.
Alternatively, you can also set your stack by using the global
variable _stklen. To change the size to, say 10,000 bytes, include
the following line in your program:

extern unsigned _stklen = 10000;

This statement must not be inside any function definition.
Windows 3.0 enforces a minimum stack size of 5K. If you specify
a size less than 5K, Windows will set the stack size to 5K.

Q. I'm getting a stack overflow message when I run my program.
How can I work around this?
A. You may increase the stack size by following the procedure above. Stack
overflows are usually caused by a large amount of local data or
recursive functions. You can decrease the amount of stack space
used by declaring your local variables static:

int foo(void) int foo(void)
{ {
char x[5000]; --> static char x[5000];
: :
} }

Of course, you should be aware that there are other effects
that the "static" keyword has, as applied here. See the Turbo
C++ for Windows Programmer's Guide.

Q. Why do I get "declaration syntax error" messages on dos.h when
using EasyWin?
A. You have set the "ANSI keywords only" option ON. Keep this
option OFF when using any keywords specific to Turbo C++ for
Windows. See the Turbo C++ for Windows Programmer's Guide
for a list of keywords. Also note that for normal Windows
applications which don't make use of EasyWin, you should use
the Turbo C++ for Windows keywords option.

Q. I am linking my own assembly language functions with Turbo
C++ for Windows. But the linker reports that all of my
functions are undefined. A. See answer above in the "Linker"
section.

Q. Why do I get incorrect results from all the math library
functions like cos(), tan() and atof()?
A. You must #include <math.h> before you call any of the standard
Turbo C++ for Windows math functions. In general, Turbo C++
for Windows assumes that a function that is not declared
returns an int. In the case of math functions, they usually
return a double. For example

/* WRONG */ /* RIGHT */
#include <math.h>
int foo(void) int foo(void)
{ {
printf("%f", cos(0)); printf("%f", cos(0));
} }

Q. I'm trying to build an app based on one of Borland's libraries
(ObjectWindows, the container classes in the CLASSLIB directory,
or the Runtime Library), and I get linker errors, or it won't run
right. What's going wrong?

A. You may be using a switch that affects linkage in your files,
that was not used when the library itself was compiled, or you
need to change the library in question. Here are some examples:

- If you use far vtables (-Vf or Options|Compiler|C++|Far
virtual tables) to compile a file you developed which
includes iostream.h, it won't build correctly until you
rebuild the iostream library with the same option.

- If you opt to use the templates implementation of the container
class library to build ObjectWindows applications, you must
rebuild the necessary ObjectWindows libraries from source
using the templates implementation of the class library
(the BIDxxxx.LIB files.)




0

评论Comments