new命令在堆中分配内存以存储对象。 静态分配可能导致将对象放在堆栈上。 但它们都不是记忆保护区。 我可以访问它,这只是对象的地址,然后使用间接运算符,所以指向对象字段:
string str=string("hello");
void** str_this=(void**)&str;
char* str_data= (char*)*str_this;
str_data[0]='s';
str_data[1]=0;
cout <<str_data; // prints "sello"
那么这仍然被认为是封装吗?是类用户(谁实例化对象)的费用,以避免poiting它的数据?
答案 0 :(得分:6)
编程中的封装通常不意味着“如果你真的真的尝试就无法解决”。
它通常意味着更接近于“能够明确区分所谓的是否暴露或不会暴露或使用的东西”。
我认为没有人会错误地将您的代码误认为是以应该访问的方式访问字符串。
答案 1 :(得分:3)
C ++是一种强大的语言。正如漫画书超级英雄曾经说过的那样,强大的力量带来了巨大的责任。
将对象指针转换为void*
然后将该指针重新转换为另一种类型(在本例中为char*
)后,您已进入未定义行为的范围。如果您尝试使用char*
指针,则该语言无法保证将会发生什么以及哪些不起作用。将void*
重新转换回原始类型(string*
)是合法的。
调用未定义的行为不是打破封装的合法方式,因为一旦你越过未定义的行为阈值,任何都是可能的(只是不可移植)。
答案 2 :(得分:2)
您的代码隐式依赖于std :: string的特定实现。换句话说,您的代码打破 std :: string的封装。更糟糕的是,它会调用未定义的行为,因此它可能有效,或者可能没有,或者它可能会崩溃......