13.1. Macro Questions

Microsoft Visual C++/Microsoft Foundation Classes


13.1. Macro Questions

13.1.1.  What's the difference between IMPLEMENT_DYNAMIC, IMPLEMENT_DYNCREATE and IMPLEMENT_SERIAL?

IMPLEMENT_DYNAMIC provides run time type information to support macros such as IsKindOf and GetRuntimeClass.

IMPLEMENT_DYNCREATE adds the ability to allow MFC to create the type on the fly. This is required for any concrete data type that will be serialized to a file.

IMPLEMENT_SERIAL also provides a version number for the class and adds the ability to use the >> operator to read the type from a file.

As an example, if a derived class Dog uses IMPLEMENT_DYNCREATE and a base class Animal uses IMPLEMENT_SERIAL, then a Dog can be written with a pointer to either but can only be read by a pointer to Animal.

MFC 3.x provides a constant called VERSIONABLE_SCHEMA to be used with IMPLEMENT_SERIAL to support multiple versions at the same time. The implementation in MFC is broken and fails at runtime.

[email protected],  email, 7/11/95

[MFC 4.0 NOTE: It is not true that the versionable schema is broken anymore, and has been fixed in MFC 4.0. ]

13.1.2.  How can I declare an abstract base class to be IMPLEMENT_SERIAL?

You need a special form of IMPLEMENT_SERIAL that looks like this: Use the regular DECLARE_SERIAL but use IMPLEMENT_SERIAL_ABC shown below instead of IMPLEMENT_SERIAL.

#define IMPLEMENT_SERIAL_ABC(class_name, base_class_name, wSchema)
_IMPLEMENT_RUNTIMECLASS(class_name, base_class_name, wSchema, NULL)
CArchive& AFXAPI operator>>(CArchive& ar, class_name* &pOb)
{
    pOb = (class_name*) ar.ReadObject(RUNTIME_CLASS(class_name));
    return ar;
}

anonymous

13.1.3.  I can't create an instance because of DECLARE_DYNCREATE!

Question : ClassWizard generated a class for me but used DECLARE_DYNCREATE(...) and declared my constructor as protected. Now, when a try to create an instance of the class I get the compiler error:

error C2248: 'CChkTbl::~CChkTbl' : cannot access protected member declared in class 'CChkTbl'

Answer : ClassWizard does this because the framework normally handles instantiation for you. i.e. if this is a CView derived class, normally the CDocumentTemplate instantiates the view during the default OnFileNew(), or when you call CxxxDocTemplate->OpenDocumentFile() or something similar. The framework does this so that it will give you an error message if you accidentally try to instantiate it yourself. If you really need to do instantiation outside of the CDocTempate framework, simply change the constructor to be public.

[email protected], programmer.tools, 8/12/95

Answer : The answer is that the DECLARE_DYNCREATE macro lays down a "protected:" directive and leaves it in place. One needs to make sure that anything following DECLARE_DYNCREATE should be "protected" too; if not, one needs to declare "public:" or "private:, as needed.

[email protected], email, 8/15/95

13.1.4.  How do I enable TRACE macros in my app?

If you use Visual C++ 1.0, run the TRACER application from your Microsoft Visual C++ program group (its icon has the title "MFC Trace Options"). Select "Enable Tracing," then choose OK.

If you use Microsoft C/C++ 7.0, you must copy the AFX.INI file from the Microsoft Foundation Class Library source directory (by default, C:\C700\MFC\SRC) to your Windows directory (by default, C:\WINDOWS). This file should contain a section such as the following:

[Diagnostics]
TraceEnabled = 1
TraceFlags = 0

As long as TraceEnabled is set to 1, tracing is enabled.

This AFX.INI file is the same for both C/C++ 7.0 and Visual C++ 1.0. In MSVC 2.x, the TRACE output automatically goes to the 'Debug' window when you run in the debugger.

VC+ Knowledge Base, 6/7/95

NEW!! 13.1.5.  Alternative to the TRACE macro

If you create the following pre-processor macro:

#ifdef _DEBUG
#define INFO ::AfxTrace("%s(%i): ",__FILE__,__LINE__); ::AfxTrace
#else
#define INFO ((void)0)
#endif

and then use this in place of a TRACE then the output is such that if you
double click on the line in the output window it takes you to the line of
code where the INFO statement is. It is great for navigating code quickly
while debugging.

Colin Mackay [[email protected]],
Sirius Seven Software Ltd.