我正在使用 C 進行繼承(即使用子類資料型別呼叫超類的函式),但遇到了別名問題。
在下面,shape函式是用rectangle物件呼叫的。
在 的情況下me->super,x和y是正確的。然而,他們在(Shape*)me.
我喜歡的原因(Shape*)me了me->super,是我想從客戶端隱藏結構的實作。
C標準不應該保證嗎?根據第 6.7.2.1.13 節
“……一個指向結構物件的指標,經過適當的轉換,指向它的初始成員。結構物件中可能有未命名的填充,但不是在其開頭”。
/*shape.h*/
#ifndef SHAPE_H
#define SHAPE_H
typedef struct Shape Shape;
Shape* Shape_ctor(int x, int y);
int Shape_getX(Shape* me);
int Shape_getY(Shape* me);
#endif
/*shape.c*/
#include <stdlib.h>
#include "shape.h"
struct Shape
{
int x;
int y;
};
Shape* Shape_ctor(int x, int y)
{
Shape* me = malloc(sizeof(struct Shape));
me->x = x;
me->y = y;
return me;
}
int Shape_getX(Shape* me)
{
return me->x;
}
int Shape_getY(Shape* me)
{
return me->y;
}
/*rectangle.h*/
#ifndef RECT_H
#define RECT_H
#include "shape.h"
typedef struct Rectangle Rectangle;
Rectangle* Rectangle_ctor(int x, int y, unsigned int width, unsigned int height);
int Rectangle_getWidth(Rectangle* me);
int Rectangle_getHeight(Rectangle* me);
#endif
/*rectangle.c*/
#include <stdlib.h>
#include "rectangle.h"
#include "stdio.h"
struct Rectangle
{
Shape* super;
unsigned int width;
unsigned int height;
};
Rectangle* Rectangle_ctor(int x, int y, unsigned int width, unsigned int height)
{
Rectangle* me = malloc(sizeof(struct Rectangle));
me->super = Shape_ctor(x, y);
me->width = width;
me->height = height;
printf("x: %d\n", Shape_getX(me->super)); //correct value
printf("y: %d\n", Shape_getY(me->super)); //correct value
printf("x: %d\n", Shape_getX((Shape*)me)); // wrong value
printf("y: %d\n", Shape_getY((Shape*)me)); // wrong value
return me;
}
int Rectangle_getWidth(Rectangle* me)
{
return me->width;
}
int Rectangle_getHeight(Rectangle* me)
{
return me->height;
}
/*main.c*/
#include <stdio.h>
#include "rectangle.h"
int main(void) {
Rectangle* r1 = Rectangle_ctor(0, 2, 10, 15);
printf("r1: (x=%d, y=%d, width=%d, height=%d)\n", Shape_getX((Shape*)r1)
, Shape_getY((Shape*)r1)
, Rectangle_getWidth(r1)
, Rectangle_getHeight(r1));
return 0;
}
uj5u.com熱心網友回復:
您應該將基型別作為第一個成員。不是指向基型別的指標。
struct Rectangle {
Shape super;
...
}
此外,您應該重新設計Shape_ctor. 我建議將指標作為引數并將記憶體管理委托給呼叫者。
Shape* Shape_ctor(Shape *me, int x, int y)
{
me->x = x;
me->y = y;
return me;
}
矩形的建構式是:
Rectangle* Rectangle_ctor(Rectangle *me, int x, int y, unsigned int width, unsigned int height)
{
Shape_ctor(&me->super, x, y); // call base constructor
me->width = width;
me->height = height;
printf("x: %d\n", Shape_getX(&me->super)); //correct value
printf("y: %d\n", Shape_getY(&me->super)); //correct value
return me;
}
典型用法:
Rectangle rect;
Rectangle_ctor(&rect, ...);
或更多異國情調的變體,例如:
Rectangle* rect = malloc(sizeof *rect);
Rectangle_ctor(rect, ...);
// or
Rectangle* rect = Rectangle_ctor(malloc(sizeof *rect), ...);
// or even kind of automatic pointer
Rectangle* rect = Rectangle_ctor(&(Rectangle){0}, ...);
只有在實作像Shape_getArea().
struct Shape {
...
double (*getArea)(struct Shape*);
};
double Shape_getArea(Shape *me) {
return me->getArea(me);
}
double Rectangle_getArea(Shape *base) {
Rectangle *me = (Rectangle*)base; // the only cast
return (double)me->width * me->height;
}
Rectangle* Rectangle_ctor(Rectangle *me, int x, int y, unsigned int width, unsigned int height) {
...
me->super.getArea = Rectangle_getArea;
...
}
// usage:
Rectangle rect;
Rectangle_ctor(&rect, 0, 0, 3, 2);
Shape *shape = &rect.super;
Shape_getArea(shape); // should return 6
編輯
為了隱藏內部結構,Shape放置一個指向其私有資料的指標。用 中的相關資料初始化這個指標Shape_ctor。
struct Shape {
void *private_data;
// non private fields
};
uj5u.com熱心網友回復:
的初始成員Rectangle是 a Shape*,而不是 a Shape。的初始成員Shape是一個 int , not a Shape*`。你假設的共性不存在。
如果您查看 C 實作如何實作繼承,在單繼承的情況下,它們會將基本子物件放置在完整物件內的偏移量 0 處。指向基類子物件的指標用于虛擬繼承,但這很快變得復雜。
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/339634.html
下一篇:呼叫了不正確的物件方法
