Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/161.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 访问说明符不是万无一失的?_C++_Macros_Encapsulation_Access Specifier - Fatal编程技术网

C++ 访问说明符不是万无一失的?

C++ 访问说明符不是万无一失的?,c++,macros,encapsulation,access-specifier,C++,Macros,Encapsulation,Access Specifier,如果我有这样的课 class Sample { private: int X; }; 那么我们不能从外部访问X,所以这是非法的 Sample s; s.X = 10; // error - private access 但是我们可以在不编辑类的情况下访问它!我们需要做的就是 #define private public //note this define! class Sample { private: int X; }; //outside

如果我有这样的课

class Sample
{
private:
      int X;
};
那么我们不能从外部访问X,所以这是非法的

    Sample s;
    s.X = 10; // error - private access
但是我们可以在不编辑类的情况下访问它!我们需要做的就是

#define private public  //note this define!

class Sample
{
private:
      int X;
};

//outside code
Sample s;
s.X = 10; //no error!
ideone的工作代码:

这意味着,我们可以通过在类定义之前或在
#include
之前定义这样的宏来更改访问说明符

这不是C++的问题(宏/访问说明符/什么)? 无论如何,本主题的重点是:


使用宏,我们很容易违反封装。访问说明符不是万无一失的我说得对吗?

首先,这样做是违法的
private
是一个关键字,不能将其用作宏中的标识符;你的程序格式不正确

但在任何情况下,这都不是宏的问题。是那个愚蠢的人以愚蠢的方式使用了它们。:)(他们在那里帮助你安全,他们不在那里帮助你安全,阻止一切进入他们,无论你尝试什么。C++保护墨菲,而不是马基雅维利。)< /P> 请注意,您可以以格式良好、定义明确的方式访问私密空间,如下所示。再说一次,这不是语言的问题,只是语言的任务不是做更多必要的事情来保持窥探的手

但是我们可以在不编辑类的情况下访问它

但是,如果不编辑包含该类的源文件,则不能执行此操作

是的,宏可以让你射自己的脚。这不是什么新闻。。。但这是一个特别不麻烦的例子,至于“违反封装”,您必须强制类定义以骨骼为头的宏本身,或者包含这样做的头文件


换一种说法:在真正负责任的软件开发中,你能看到这是一个问题吗?

不。它会破坏私有方法的破坏性。如果编译器能够判断这些私有方法不能在其他地方访问,那么它们可以内联并优化,并且它们可能不会出现在目标文件中,因此它们将无法访问

以此为例,。它要么工作,要么无法链接,要么无法运行可执行文件,这取决于您使用的优化/剥离标志以及编译方式(即,您是否可以将实现放入共享库)

实施文件:

#include <iostream>
#include "a.h++"

// uncomment this for more g++ fun
// __attribute__((visibility("hidden")))
void A::stupid_private() {
        std::cout << "let's output something silly." << std::endl;
}
void A::unlock(std::string password) {
        if (password == "jumbo")
                stupid_private();
}
但是我们可以让它无需编辑类即可访问!我们需要做的就是

#define private public  //note this define!

class Sample
{
private:
      int X;
};

//outside code
Sample s;
s.X = 10; //no error!
从技术上讲,您所展示的只是“我们可以将一个法律程序变成未定义的行为”,而无需编辑一个特定的类

这可不是什么新闻。您还可以通过在
main()
的末尾添加这样一行,将其变成未定义的行为:

<> > C++中的访问说明符不是安全特性,它们不能防止黑客攻击,它们不能防止人们故意将错误引入到代码中。 它们只允许编译器帮助您维护某些类不变量。它们允许编译器在您意外尝试访问私有成员时通知您,就像它是公共成员一样。你所展示的只是“如果我特别想破坏我的程序,我可以”。希望这不会让任何人感到惊讶


< @ Gman说,重新定义C++语言中的关键字是未定义的行为。它可能在你的编译器上工作,但是它不再是一个定义良好的C++程序,编译器可以在原则上做任何它喜欢的事情。p> @Nawaz,你的帖子很有趣,我以前从没想过这个。但是,我相信你的问题的答案很简单:把C++(或者任何语言)的安全性看作是组织代码的一种方式,而不是警察。 基本上,因为所有变量都是在您自己的代码中定义的,所以无论您在哪里定义它们,您都应该能够访问它们。因此,您发现一种访问私人成员的方法并不奇怪

实际上,有一种更简单的方法可以访问私有变量。假设您有一个包含此类的库:

class VerySecure
{
private:
    int WorldMostSecureCode;
};
假设我在代码中使用了非常安全的类。我可以通过以下方式轻松访问私人会员:

VerySecury a;
int *myhacker = (int*)(&a);
int b = (*myhacker);
printf("Here is your supposed world secret: %d :-) \n", b);

这是怎么回事

您说过“private是一个关键字,您不能在宏中使用它作为标识符;您的程序将是格式错误的”。。。你怎么能这么说?《标准》是这么说的吗?@Nawaz:看。据我所知,这并没有使程序格式错误。它所做的是导致C++0x中出现未定义的行为。它在C++03中定义良好;但无论如何都不是好的样式,而且一旦包含了任何标准的标题,行为也没有定义。@Johannes:为什么在C++03中定义良好?实现需要发出错误消息,这可能是原因吗<代码> 7.63.3/2说:“如果一个程序在它保留的上下文中声明或删除一个名称,除了这个子句所明确允许的之外,它的行为是未定义的< /代码> @ Prason i是部分错误的。”良好成形的“定义为“根据语法规则、可诊断语义规则构造的C++程序,还有一个定义规则“-如果你重新定义关键字并滥用它来读取私有成员,你就违反了一个定义规则,有一个格式错误的程序:)但我不认为仅仅重新定义关键字的行为是格式错误的。我认为,在任何情况下都不需要诊断。它在C++03中定义得很好,因为没有任何东西说它是未定义的,如果你只是重新定义关键字而不包括标准标题:)@Jon:如果我可以访问私有成员,那么显然这是一个问题。你不这么认为吗?我可以在包含向量类之前定义private-public,并更改向量类的行为(如果故事中没有任何其他扭曲)。@Nawaz:是的,你可以,但不,这不是问题。别那么做。如果我不经意地接触到私密处,那将是一个问题,这里不是这样。@GMan:你不理解我。访问规范的目的是什么
int i = 0;
i = ++i;
class VerySecure
{
private:
    int WorldMostSecureCode;
};
VerySecury a;
int *myhacker = (int*)(&a);
int b = (*myhacker);
printf("Here is your supposed world secret: %d :-) \n", b);