The previous section describes a simple object structure in pure C language. Because examples are used to demonstrate the structure, we will design the Crest syntax this time, that is to say, let's take a look at what the programming code will look like if Crest can be successfully completed.
The ideal object-oriented syntax is, of course, a structure like C # And java. However, because the C language uses header files, it is estimated that the final style is similar to C ++. First, we need to create a target style, and then use Crest to simulate the implementation. The goal is [Code 1]:
class CString: CObject, IUnknown, IDispatch
{
int length;
char * buffer;
public virtual void Format(char * format)
{
DoFormat(format);
}
public void DoFormat(char * format)
{
if( OnFormat != null ) OnFormat(format);
}
public abstract void OnFormat(char * format);
}
To use Crest to implement the above structure, pay attention to the following issues:
- This pointer. All object member definitions and calls have an implicit this pointer.
- Naming Conventions: CString Format and CDateTime Format are definitely not the same thing, but the C language does not support override, so ensure that the member functions are not renamed.
After two days of intermittent work, the final result is as follows [Code 2]:
DECLARE_CLASS(CString)
EXTENDS(CObject, IMPLEMENT2(IUnknown,IDispatch))
DECLARE_FIELD(CString, int, length)
DECLARE_FIELD(CString, char *, buffer)
DECLARE_VIRTUAL1(CString, void, Format, const char * format)
DECLARE_ABSTRACT1(CString, void, OnFormat,const char * format)
DECLARE_METHOD1(CString, void, DoFormat,const char * format)
DECLARE_CONSTRUCTOR(CString)
DECLARE_DESTRUCTOR(CString)
END_DECLARE(CString);
Does this style seem cumbersome? Bigtall began to feel unsatisfied, but later found that with the help of Macro magic in C language, such a structure is the simplest, or better!
Before the final evolution to the Code style like this, we can manually implement a version without macro. The truth is true only when there is a comparison! For more information, see section (Code 1). Based on the experience gained above, you can easily give the code to [Code 3]:
struct Class_CString;
typedef struct Class_CString CString;
void CString_Format (CString *self, const char * format);
void CString_OnFormat (CString *self, const char * format);
void CString_DoFormat (CString *self, const char * format);
void CString_constructor (CString *self);
void CString_destructor (CString *self);
struct Class_CString{
int length;
char * buffer;
void (*Format) (CString *self, const char * format);
void (*OnFormat) (CString *self, const char * format);
};
Writing a lot of things is troublesome. If we add more features in the future, I am afraid it will become a nightmare. To allow others to use the Crest, the syntax must be "cost-effective"-adds a certain amount of complexity, but provides more useful features. To implement the conversion from Code 2 to Code 3, let's take a look at the actual header file definition (Code 2:
/* filename: macropure.h */
#if defined(DECLARATION) || defined(DEFINITION)
#include "CrestMacro.h"
DECLARE_CLASS(CString)
.../* Omitted here */
END_DECLARE(CString);
#else
#define DECLARATION
#include "macropure.h"
#undef DECLARATION
#define DEFINITION
#include "macropure.h"
#undef DEFINITION
#endif
Bigtall uses a large number of macro definitions and uses a seldom used feature: include yourself. Through its own inclusion, combined with # if... # else... # endif, we have implemented different definitions of DECLARE_CLASS at different stages. The result of this operation is to write a tedious definition and implement the complete class definition code through macro conversion. Unfortunately, if # include also supports macro extension, the header file can be simpler. In addition, bigtall also implements a version that uses cpp32 preprocessing to include the. I file. Due to the portability problem, it is not necessary.
The above is the. h header file. For the. c file, the Crest code is as follows:
#include <stdio>
#include "macropure.h"
IMPL_VIRTUAL1(CString, void, Format, const char * format)
{
REF_METHOD(CString, DoFormat)(self, format);
}
IMPL_ABSTRACT1(CString, void, OnFormat,const char * format)
{
puts(format);
}
IMPL_METHOD1(CString, void, DoFormat,const char * format)
{
if( self->OnFormat != 0 )
self->OnFormat(self, format);
}
IMPL_CONSTRUCTOR(CString)
{
self->length = 3;
self->buffer = "abc";
self->Format = REF_METHOD(CString, Format);
self->OnFormat = REF_METHOD(CString, OnFormat);
}
IMPL_DESTRUCTOR(CString)
{
}
void main()
{
CString str, *pStr;
CONSTRUCT(CString, &str);
NEW(CString, pStr);
str.Format(&str, "abcdefg\n");
pStr->Format(pStr, "cdefghijk\n");
DELETE(CString, pStr);
DESTRUCT(CString, &str);
}
Previous Article: Design of simple Crest objects (to be continue)