- 论坛徽章:
- 0
|
详解EXTENDS2
EXTENDS宏可以完成一般的继承功能,但有个小问题:
typedef struct CBase { VT(VBase) ... } CBase;
typedef struct CThis { EXTENDS(CBase) ... } CThis;
CThis t; //t.vt
VT宏是定义虚函数指针vt,t.vt的类型是const VBase*,而实际上
CThis扩展了虚函数表类VThis,希望t.vt的类型是const VThis*
才方便,用强制类型转换肯定行,但不安全.用数据覆盖!只听说函
数覆盖,数据也能覆盖吗?定义同名数据,排在前面的可访问,后面
的被覆盖:
#define EXTENDS2(s,v) \
union \
{ \
VT(v) \
EXTENDS(s) \
};
typedef struct CThis { EXTENDS2(CBase,VThis) ... } CThis;
这样一来,t.vt就是const VThis*,而t.CBase.vt是const VBase*,
它由于重名的原因,失去了跨层访问待遇.合并两个union得到最终
版本:
#define EXTENDS2(s,v) \
union \
{ \
VT(v) \
s s; \
s; \
};
最后谈谈编译器支持,同名数据覆盖,C标准没说,很多编译器支持,
gcc和tcc都没问题.
但也带来一个问题:union的默认初始化.CThis t={...};
C标准没说,有些编译器不支持,如tcc,现已修改好了;gcc初始化第
一个,那么只能初始化vt,而其它数据将被忽略,这决不是我们所愿.
将初始化改为最后一个就可以躲开了,反正C标准没定义,怎么都合
理.现阶段gcc没改好,但可以用C99标准的指定初始化代替:
CThis t={.CBase={..};};
而一般用不着这种初始化,用构造函数CThis_CThis(&t); |
|