4.7 子类的实现 - 环
我们已经做好了些完整实现的准备,我们可以选择先前部分介绍的我们最喜欢的技术。面向对象规定我们需要一个构造器,可能的话还会有一个析构器, Circle_draw()
,和类型描述 Circle
都绑定在一起。以便于练习我们的方法,我们包含了 Circle.h
并增加了下面的行在 4.1 部分的程序中做测试:
case 'c':
p=new(Circle,1,2,3);
break;
现在我们能够观察到下面的测试程序的表现:
$ circles p c
"." at 1,2
"." at 11,12
circle at 1,2 rad 3
circle at 11,22 rad 3
环的构造函数接收 3 个参数:第一个参数为环的点的坐标接下来是半径。初始化点部分是点的构造器的工作。它会处理部分 new()
参数列表的参数。环的构造器从它的初始化半径的地方携带保留的参数列表。
一个子类的构造器首先应该允许超类做部分初始化,这部分初始化把清晰地内存带进超类对象。一旦超类构造器构造完成,子类构造器完成初始化并把超类对象带进子类对象中。
对于环,意味着我们需要调用 Point_ctor()
。像其他所有动态链接一样,这个函数被声明为 static
,因此隐藏在 Point.c
的内部。然而,我们仍然能够通过在 Circle.c
中可用的类型描述符来 Point
获得此函数。
static void * Circle_ctor (void * _self, va_list * app)
{
struct Circle * self =
((const struct Class *) Point) —> ctor(_self, app);
self —> rad = va_arg(* app, int);
return self;
}
这里应该很清楚为什么我们传递参数的地址 app
列表指针到每个构造器而不是 va_list
的值本身: new()
调用子类的构造器,此构造器调用超类的构造器,等等。最超级的构造器是第一个将去实际的作一些事情,并且会捡起传进 new()
的最左边的参数列表。保留的参数对于下一个子类是可用的,等等知道最后,最右边的参数被最终的子类所使用,也就是说,被 new()
所直接的调用的构造器所调用。
构造器以严格的相反的次序是最好的组织: delete()
调用子类的析构器。它首先应该销毁它自己的资源接下来调用直接的超类的析构器,这个析构器可直接的销毁下一个资源集等等。构造是先发生在子类之前的父类上的。析构则是相反,子类要先于父类,即,环部分要先于点部分。这里,然而,什么也不需要做。
我们先前已经让 Circle_draw()
工作了,我们使用可见部分,并且编码表示文件 Point.r
如下:
struct Point {
const void * class;
int x, y; /* coordinates */
};
#define x(p) (((const struct Point *)(p)) -> x)
#define y(p) (((const struct Point *)(p)) -> y)
现在我们可以对于 Circle_draw()
使用访问宏:
static void Circle_draw (const void * _self)
{
const struct Circle * self = _self;
printf("circle at %d,%d rad %d\n",x(self), y(self), self —> rad);
}
move()
拥有静态链接并且被从点的实现上继承。我们得出结论环的实现是通过定义仅仅全局可见 Circle.c
的部分内容:
static const struct Class _Circle = {
sizeof(struct Circle), Circle_ctor, 0, Circle_draw
};
const void * Circle = & _Circle;
然而,在接口,表示式,实现文件之间似乎我们有一个可行的分配程序文本实现类的策略,点和环的例子还没有显现出一个问题:如果一个动态连接的方法如 Point_draw()
在子类中没有被重写,子类的类型描述符需要指向在父类实现的函数。函数名,然而在这里被定义成 static
,因此选择器是不能够被规避的。我们将在第六章看到一个清晰地解决此问题的方法。作为暂时的权衡,我们在这种情况下可以避免对 static
的使用,仅仅在子类的实现文件中声明函数的头,对于子类并且使用函数名去初始化类型描述。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论