PRODUCT : Borland C++ NUMBER : 8504 VERSION : ALL OS : ALL DATE : October 25, 1993 PAGE : 1/9 TITLE : C++ Language News -- Volume 1, Number 5 _C++ Support News_ ---------------------------------------------------------------- volume 1, number 5 May 17, 1993 ---------------------------------------------------------------- IMPORTANCE OF COPY-CONSTRUCTORS The importance of copy-constructors in C++ cannot be over- emphasized. A copy constructor is invoked whenever a new instance of a class is created from an existing instance. Copy-constructors follow the form: classname(classname &instance) { } The following C++ program does not contain a copy-constructor. 1. #include 2. #include 3. class string { 4. char *s; 5. public: 6. string(char *p) { 7. s = new char[strlen(p) + 1]; 8. strcpy(s, p); 9. } 10. ~string() { delete [] s; } 11. }; 12. void main() { 13. string s("foobar"); 14. string w = s; 15. } Simple inspection shows that the class constructor and de- structor gets called twice. The first destructor call destroys string instance w, and the second destroys s since destructors are called in the opposite order of creation. It is to be noted, however, that a null-pointer assignment will occur on line 15 if this program is compiled in the small or medium memory models. The reason for this error message is due to the type of copy- constructor generated by the compiler. The language specifi- cation for C++ states that if a copy-constructor is not ex- PRODUCT : Borland C++ NUMBER : 8504 VERSION : ALL OS : ALL DATE : October 25, 1993 PAGE : 2/9 TITLE : C++ Language News -- Volume 1, Number 5 plicitly given within the code, a bitwise copy, or "shallow" copy should be generated by the compiler for usage. If code were to be created for this implicit constructor, it would appear as -- string(string &arg) { s = arg.s; } Note that no new heapspace is allocated in the new string in- stance. Because both instances in this situation are pointing to the same heapspace allocation, the second destructor call attempts to free previously released memory. This is the cause of the null-pointer assignment message generated at runtime. The programmer can avoid this problem by creating a copy-con- structor which will perform memory allocation itself. In con- trast to the "shallow" copy-constructor above, an explicit copy-constructor could be termed as "deep". Hence, string(string &arg) { s = new char[strlen(arg.s) + 1]; strcpy(s, arg.s); } As opposed to simply copying the value of the pointer, this explicit copy-constructor allocates heapspace itself prior to copying the contents of the previous instantiation's inter- nal string. Addition of this copy-constructor makes each class instantiation independent. Defensive programmers will include a copy-constructor in each class definition; this can avoid the confusion when determining whether a copy-constructor or assignment operator is called. Be aware that copy-constructors will be used in the following situ- ations: 1. when a new class instance is created from an existing instantiation. 2. when a class instance is passed by value. 3. when a class instance is returned from a function or member function. * * * * * PRODUCT : Borland C++ NUMBER : 8504 VERSION : ALL OS : ALL DATE : October 25, 1993 PAGE : 3/9 TITLE : C++ Language News -- Volume 1, Number 5 An apparent incompatibility exists with the Resource Workshop 1.02 and the BWCC.DLL coming from Paradox for Windows 1.0 or Borland Pascal 7.0 when editing dialog boxes and using Borland custom controls. The problem presents itself when editing .RC files. When the problem manifests itself, a "Resource Workshop 164 : Compile error" or "Incomplete expression" message box will be presented to the user. To reproduce the effect, add a Bor- land group box resource to a new dialog, double click on the control to gain access to the style dialog, and press "OK". If the previous messages are displayed, the defines given below need to be added to the .RC file. Despite its appearance, the Resource Workshop version 1.02 is compatible with the newer BWCC.DLL, but additional defines (listed below) are required. These can be placed in a header file by themselves or added to the BWCC.H file coming with Borland C++ 3.1. If these are added to BWCC.H, they should be added after the line containing -- #define BSS_DLGERASE ... A new version of BWCC.DLL (dated 03-09-93) which is available on Borland's DLBBS and CompuServe's BCPPWIN LIB-2 contains a new BWCC.H header file that includes these define statements. This file should be copied into the standard Borland C++ in- clude subdirectory. You should also #include in your resource files that use the Borland group box. The following define statements have been added to the newest version of BWCC.H: #define BSS_GROUP 1L // recessed group box #define BSS_HDIP 2L // horizontal border #define BSS_VDIP 3L // vertical border #define BSS_HBUMP 4L // horizontal speed bump #define BSS_VBUMP 5L // vertical speed bump #define BSS_RGROUP 6L // raised group box #define BSS_CAPTION 0x8000L // set off the caption #define BSS_CTLCOLOR 0x4000L // send WM_CTLCOLOR // messages to parent // of control #define BSS_NOPREFIX 0x2000L // & in caption does // not underline fol- // lowing character #define BSS_LEFT 0x0000L // caption is left- // justified PRODUCT : Borland C++ NUMBER : 8504 VERSION : ALL OS : ALL DATE : October 25, 1993 PAGE : 4/9 TITLE : C++ Language News -- Volume 1, Number 5 #define BSS_CENTER 0x0100L // caption is centered #define BSS_RIGHT 0x0200L // caption is right- // justified #define BSS_ALIGNMASK 0x0300L DOS 1. How can I JMP or CALL an address that is not defined as a procedure or label? The first thing necessary is to define a double (DD). MyStruc STRUC OFFSET_VALUE DW ; segment & offset SEGMENT_VALUE DW ; note reverse order MyStruc ENDS SmallUnion UNION DPTR DD ; forces a far call ADDR MyStruc SmallUnion ENDS JumpLocation SmallUnion Assuming that the desired destination is 0F00H:0600H .CODE ; ... MOV JumpLocation.ADDR.OFFSET_VALUE, 0600H MOV JumpLocation.ADDR.SEGMENT_VALUE, 0F00H CALL JumpLocation.DPTR ; ... The structure within the union allows easy loading of the values. An alternative and shorter method is to use -- .DATA FarLabel DD .CODE ; ... MOV WORD PTR [FarLabel], 0600H MOV WORD PTR [FarLabel + 2], 0F00H PRODUCT : Borland C++ NUMBER : 8504 VERSION : ALL OS : ALL DATE : October 25, 1993 PAGE : 5/9 TITLE : C++ Language News -- Volume 1, Number 5 CALL FarLabel ; ... Likewise in Ideal mode, an absolute jump can be done by the following -- IDEAL CODESEG Start: ; ... JMP FAR 0F00H:0600H ; ... end Start OS/2 1. Suppose you have a 16-bit DLL (like many database DLL's) and you want to use it from your 32-bit application. Here's what you'll need to do for prototypes of the DLL's functions: * 16-bit functions returning an int should be prototyped as returning a short, since 16-bit int's are now con- sidered 'short' (APIRET16 is the typedef for it in OS2DEF.H) * The function should be declared as APIENTRY16, or, _far16 _pascal * Any pointers that the function takes as parameters must be declared as _far16 eg. former prototype in FOO.H (FOO.DLL's associated header file): int FooData(char *, int); new prototype for linking 32-16 (in your Borland C++ program): short _far16 _pascal FooData(char _far16 *, short); Note: don't use char * _far16 ... PRODUCT : Borland C++ NUMBER : 8504 VERSION : ALL OS : ALL DATE : October 25, 1993 PAGE : 6/9 TITLE : C++ Language News -- Volume 1, Number 5 It's easy to make this mistake since IBM's pointers are de- clared with _Seg16 after the '*'. If you wanted to use the types declared in OS2DEF.H, it would be: APIRET16 APIENTRY16 FooData(PCHAR16, SHORT); The compiler will take care of the address conversions for the function and the data being passed. Notes: * Most DLL's should be called with the _pascal calling convention. Sybase is an exception, needing to be called as _cdecl. * It's difficult to pass a 32bit function pointer to be executed from a 16-bit DLL ("callback") and how to do it is beyond the scope of this article. * Functions in a 16bit DLL that take variable argument lists (eg. printf()) are not usable. The compiler cannot know to convert their addresses. * An array of pointers cannot be converted, for the same reason. WINDOWS 1. When I use a common dialog in ObjectWindows, it comes up fine, but when I switch away to the application and bring up another dialog of the same type, it does not appear to be operating as a modal dialog. Why? The hwndOwner data member of the initializing structure of a common dialog identifies the window that owns it. This is the window that the common dialog will be modal for in communication. If the common dialog structure is init- ialized in the constructor of a TWindow descendent, the HWindow is not valid, and the dialog will behave as de- scribed above. Similarly, if the hwndOwner member is NULL, the dialog has no owner and can be switched away. The solution to this behaviour is to not initialize the hwndOwner member of the structure until SetupWindow(). PRODUCT : Borland C++ NUMBER : 8504 VERSION : ALL OS : ALL DATE : October 25, 1993 PAGE : 7/9 TITLE : C++ Language News -- Volume 1, Number 5 TURBO VISION 1. I get "Undefined symbol tapplication::~tapplication()..." when linking my project. What is wrong? TV.LIB was not included. Be sure that Turbo Vision is se- lected under Options|Linker|Libraries. If TV.LIB is not specified, another undefined symbol may include tproginit::tproginit(tstatusline far*(far*)(trect), tmenubar far*(far*)(trect),[]far*). 2. I receive a "Fixup overflow at _TEXT::0047, target = operator new()...". Why is this? The project needs to be compiled in the large memory model; no other model will work. This error message will most likely be obtained if compiling is done with a compiler earlier than Borland C++ 3.0. You might also see "Fixup overflow at _TEXT::0059, target = operator >>()..." or "Fixup overflow at _TEXT::0059, target = tapplication::~tapplication...". PARADOX ENGINE 1. Can the Paradox Engine by overlayed? Engine applications can be overlayed with Borland C++, Borland Pascal 7.0, or Turbo Pascal 6.0 or 7.0 in the DOS environment (with the exclusion of Paradox Engine version 1.0). Large applications can be fairly slow if the over- lay buffer is not increased (using the global variable _ovrbuffer) to approximately 0x2000. Increasing this value is described in the Borland C++ _Programmer's Guide_. 2. How do I call the Paradox Engine from within Visual Basic? The file VBPXENG.ZIP, available on the Borland DLBBS at (408)431-5096 or via CompuServe (GO BDEVTOOL, LIB 3), describes how to call the Engine from Visual Basic. There are other files in the same section on CompuServe which have more information and examples. Further information can be found on Microsoft's Visual Basic forum on Compu- PRODUCT : Borland C++ NUMBER : 8504 VERSION : ALL OS : ALL DATE : October 25, 1993 PAGE : 8/9 TITLE : C++ Language News -- Volume 1, Number 5 Serve. Currently, Borland does not provide support for any language besides C/C++ and Pascal. QUIZ Why is an ambiguity generated by the following code? What can be done to correct this? #include class foo { public: void member(foo&) { cout << "foo::member()" << endl; } }; class bar { public: void member(bar&) { cout << "bar::member()" << endl; } }; class foobar : public foo, public bar { }; main() { foo f; bar b; foobar fb; fb.member(f); fb.member(b); return 0; } NEW TECHNICAL INFORMATION DOCUMENTS AVAILABLE Some of the latest technical information documents available to customers include the following. 863 Brief summary of how Borland C++ 3.x allocates memory in a Windows application when calling malloc(), calloc(), and new. 1037 Configuring Turbo Debugger for Windows. 1150 Hints on dealing with "Fixup overflow" messages from TLINK. PRODUCT : Borland C++ NUMBER : 8504 VERSION : ALL OS : ALL DATE : October 25, 1993 PAGE : 9/9 TITLE : C++ Language News -- Volume 1, Number 5 1170 Explanation of random or strange keyboard behaviours while using the DOS IDE. 1288 Creating a DLL to be used with Paradox for Windows 1.0. 1294 Example of using streams in binary mode. 1326 Accessing and using the features found in the later version of BWCC.DLL shipped with Paradox for Windows 1.0. 1334 Explanation of virtual member function hiding. These documents can be found on either LIB-2 of BCPPDOS and BCPPWIN under CompuServe, Borland's DLBBS at (408)431-5096, TechFAX at (800)822-4269, or OAS at (408)431-5250. DISCLAIMER: You have the right to use this technical information subject to the terms of the No-Nonsense License Statement that you received with the Borland product to which this information pertains.