根据site:
您不能隐式地从void*
分配给任何其他类型。例如,以下内容在 C 中完全有效(事实上,它可以说是在C中执行此操作的首选方式)
int *x = malloc(sizeof(int) * 10);
但它不会在 C ++中编译。
Bjarne Stroustrup 本身的解释是,这不是安全的类型。这意味着您可以拥有一个指向任何内容的void*
,如果您将存储在该void *中的地址分配给另一个不同类型的指针,则不会发出任何警告关于它。
请考虑以下事项:
int an_int;
void *void_pointer = &an_int;
double *double_ptr = void_pointer;
*double_ptr = 5;
cout<<an_int<<endl;
当您为*double_ptr
赋值5时,它会写入8个字节的内存,但整数变量an_int
只有4个字节。因此,当您打印an_int
变量的值时,输出将为0,因为根据4字节编译器选择5(5.000 ..)的最低有效位为0.
在 C ++ 中,强制从void指针进行强制转换会让程序员注意这些事情。因此,在该语言中隐含地禁止从void *
进行类型转换以提供更强的类型安全性。
但在本例中我将void *
转换为double *
时,我感到很困惑,如:
int an_int;
void *void_pointer = &an_int;
double *double_ptr = (double *)void_pointer;
*double_ptr = 5;
cout<<an_int<<endl;
输出将保持为0。
那么类型安全在这里扮演什么样的角色?什么Bjarne Stroustrup解释了类型安全?
答案 0 :(得分:4)
'Type-Safety'表示编译器不允许您使用非匹配类型进行操作,除非您明确要求这样做(例如,执行c-style或c ++ reinterpret_cast<>
类型转换,正如你在样本中所做的那样)。
答案 1 :(得分:0)
强静态类型安全性是C ++的核心元素。它基本上意味着您只能在兼容的类型之间传输信息,并且任何类型的兼容类型都是非常类型的。这个想法强化了使用具有相同类层次结构的派生类型的基类型的方法等等,以获得极大的复杂性和逻辑强度。还有一个核心思想是C ++仍然尽可能与C兼容。其中一个问题是void *
与任何指针类型兼容。但是,通常最好避免使用,因为在C ++中总是有更好的设计。
答案 2 :(得分:-1)
我无法抗拒。 “Type Safety”是一个C ++营销插科打..请考虑以下代码:
#include <stdio.h>
class A {
public:
int x;
};
class B : public A {
// B is derived from A, which makes
// B "compatible" to A
public:
// B adds a 2nd member, which means
// that B is "bigger" than A
int y;
};
int main()
{
B a1[10];
A *a2;
a2 = a1; // this is legal :-(
a1[0].x=1;
a1[0].y=1;
a2[0].x=2;
a2[1].x=3; // Upps: this probably overwrites a1[0].y
printf("a1[0].x = %d\n",a1[0].x);
printf("a1[0].y = %d\n",a1[0].y);
return 0;
}
使用“g ++ -Wall -pedantic -fstrict-aliasing”或您找到的任何其他选项进行编译。我至少没有设法发出警告。上面的代码确实不使用任何类型强制转换,但仍然会得到破坏的代码,或者至少肯定不会执行您认为应该执行的操作。
C ++大师现在可能会建议使用“vector”或其他任何东西。但那不是重点。重点是C ++ 不类型安全。
修改强>: 由于这似乎令人困惑,这里解释了问题的根源。
因为C ++是面向对象的“B类”与“A类”兼容(因为“B类”是从“A类”派生的)。这意味着您可以在需要“A类”对象的地方使用“B类”对象。这反过来意味着你可以在需要“class A *”指针的地方使用“B类*”指针。
现在的问题是C ++允许指针算术(因为它的C遗留)。指针算法与继承和兼容类型的交互非常糟糕。因为在上面的示例中,“a2 + 1”(a2是“A *类”指针)导致的地址与“a1 + 1”不同(a1是“B类*”指针)。
总结一下:C ++认为类型“class B *”与“class A *”类型兼容,但不幸的是,当你将它们用于指针算术时,这些类型不兼容。