【发布时间】:2019-12-05 18:11:52
【问题描述】:
我正在学习面向对象的 C 编程(如何实现虚拟表),我看到了一些用于初始化的铸件,我想知道是否:
1 - 是否有任何未定义的行为?
2 - 此代码是否可移植?
3 - 它在 C++ 中是否也有效(定义明确且可移植)?
在我研究的实际代码中,不是像这里这样简单的数据成员,而是指向构造函数、析构函数和克隆函数的函数指针,但我只对这些类型的转换是否定义良好感兴趣。
此代码使用 gcc 和 g++ 按预期编译和运行。
struct Point
{
int x;
int y;
};
struct Square
{
struct Point *topLeft;
struct Point *bottomRight;
int area;
};
int main()
{
void *square = calloc(1,sizeof(struct Square));
* (struct Point **) square = (struct Point *) calloc(1,sizeof(struct Point));
* ( ( (struct Point **) square) + 1) = (struct Point *) calloc(1,sizeof(struct Point));
struct Square *sqrptr = (struct Square *) square;
sqrptr->topLeft->x = 2;
sqrptr->topLeft->y = 3;
sqrptr->bottomRight->x = 5;
sqrptr->bottomRight->y = 7;
sqrptr->area = 20;
printf("Values: %d %d %d %d\n", (** (struct Point **) square).x,
(** (struct Point **) square).y,
(** ( ( (struct Point **) square) + 1) ).x,
(** ( ( (struct Point **) square) + 1) ).y );
free(sqrptr->topLeft);
free(sqrptr->bottomRight);
free(sqrptr);
}
另外,根据 valgrind,没有内存泄漏。
编辑:我只是尝试使用 C++ 风格的铸件,g++ 没有给出任何错误或警告消息。
【问题讨论】:
-
void *square应该是struct Square *square -
* (struct Point **) square应该是square->topLeft -
* ( ( (struct Point **) square) + 1)应该是square->bottomRight -
那么你的代码就更简洁了,不需要强制转换。
-
如果你没有强制转换,编译器会给你什么错误?这就是您应该关注的内容,因为您现在拥有的代码实际上除了告诉编译器“闭嘴,我知道我在做什么”之外什么都不做,完全绕过了 C++ 的类型安全性。