访问私有成员

发布于 2024-07-17 02:55:31 字数 1431 浏览 6 评论 0原文

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(12

喜你已久 2024-07-24 02:55:31

我们暂时不考虑道德。 我们来考虑一下标准。

您提议做的事情是不标准的。 参见标准第 9.2 节第 12 条。 “由访问说明符分隔的非静态成员的分配顺序未指定。” 因此,如果您有一个包含私有成员的类和一个没有私有成员的结构,则该标准不保证成员的顺序相同。

因此,如果你的 hack 起作用了,那么它的起作用只是偶然的,因为编译器作者碰巧这样做了。 不能保证它可以在另一个编译器、同一编译器的更高版本或具有不同的类布局的情况下工作。

更不用说,如果您无权修改该类(例如,提供一个简单的访问器函数),那么您可能无权反对类中的任何实现细节发生更改。 (公共和私人背后的想法之一是区分承诺的内容和可自由更改的内容。)因此,布局可能会改变,或者成员可能会意味着不同的东西,或者被完全删除。

Herb Sutter 就此问题撰写了本周大师专栏。

哦,至于道德吗? 如果你真的、真的必须做这样的事情,并且你无法摆脱它,那么请非常仔细地记录下来。 如果您的编码标准有某种标记非标准行为的程序,请使用它们。 如果没有,请非常小心地记下它,以便在出现问题时不会被忽视。

Let's not consider ethics for a moment. Let's consider the standard.

What you are proposing to do is nonstandard. See section 9.2, clause 12 of the standard. "The order of allocation of nonstatic members separated by an access-specifier is unspecified." Therefore, if you have a class with private members, and a struct with no private members, the standard does not guarantee that the members will be in the same order.

Therefore, if your hack works, it works only by accident, that the compiler writers happened to do it that way. There is no guarantee that it will work on another compiler, a later version of the same compiler, or with different class layouts.

Not to mention that, if you don't have authority to modify the class (say, to provide a simple accessor function), you probably don't have authority to object if any implementation detail in the class changes. (One of the ideas behind public and private is to distinguish what is promised from what is freely changeable.) Therefore, the layout may change, or the member might come to mean something different, or be removed altogether.

Herb Sutter wrote a Guru of the Week column on this issue.

Oh, as far as the ethics go? If you really, really have to do something like this, and you can't get out of it, document it very carefully. If your coding standards have some sort of procedure to flag nonstandard behavior, use them. If not, be very careful to note it in a way it won't be overlooked when something goes wrong.

荭秂 2024-07-24 02:55:31

我不确定“道德”是否真的参与其中。 不过,它打破了封装。

编辑:如果我正在执行代码审查,我几乎永远不会接受这一点。 你必须非常努力工作才能让我相信没有办法围绕这个需求进行设计。 你可能会成功,但必须到处都有重大警告,并且必须进行坚如磐石的单元测试,以确保如果有任何改变破坏它,你很快就会知道。

I'm not sure that "ethics" really come into it. It busts the heck out of encapsulation though.

EDIT: I would almost never accept this if I were performing a code review. You'd have to work really hard to convince me there's no way of designing around the need for this. It's possible you'd succeed, but there'd have to be major warnings all over the place, and rock hard unit tests to make sure that if anything changed to break it, you'd know quickly.

赴月观长安 2024-07-24 02:55:31

我刚刚在我的博客中添加了一个条目< /a> 展示了如何以完全一致的方式完成它。 下面是一个关于如何将它用于以下类的示例,

struct A {
private:
  int member;
};

只需声明一个标签名称并实例化一个强盗,如下例所示(我的帖子显示了强盗的实现)。 然后,您可以使用成员指针访问该成员。

struct Amem { typedef int type; };
template class rob<Amem, &A::member>;

int main() {
  A a;
  a.*result<Amem>::ptr = 42; // Doh!
}

但实际上,这并不表明 c++ 的访问规则不可靠。 语言规则旨在防止意外错误 - 如果您尝试窃取对象的数据,语言按设计不会花很长时间来阻止您。


以上是一种以一致的方式访问私有成员和受保护成员的方法。 这是以符合标准的方式访问受保护成员的另一种方式。 基本思想是使用成员指针,

std::deque<int> &getAdapted(std::stack<int> &s) {
    struct voyeur : stack<int> 
    { using stack<int>::c; };
    return s.*(&voyeur::c);
}

int main() {
    std::stack<int> s;
    std::deque<int> &adapted = getAdapted(s);
    output(adapted); // print the stack...
}

不涉及强制转换或类型双关。 它通过从其派生的类获取指向 std::stack受保护成员的指针,其中该成员名称是公共的,因此编译器允许这样做。 然后它在 std::stack 对象上使用它,这也是允许的。

I've just added an entry to my blog that shows how it can be done in a completely conforming way. Here is an example on how you use it for the following class

struct A {
private:
  int member;
};

Just declare a tag name and instantiate a robber like the following example shows (my post shows the implementation of the robber). You can then access that member using a member pointer

struct Amem { typedef int type; };
template class rob<Amem, &A::member>;

int main() {
  A a;
  a.*result<Amem>::ptr = 42; // Doh!
}

But actually, this doesn't show that c++'s access rules aren't reliable. The language rules are designed to protect against accidental mistakes - if you try to rob data of an object, the language by-design does not take long ways to prevent you.


The above is a way to access private and protected members in a conforming way. This one is another way to access protected members in a Standard conforming way. The basic idea is to use a member pointer

std::deque<int> &getAdapted(std::stack<int> &s) {
    struct voyeur : stack<int> 
    { using stack<int>::c; };
    return s.*(&voyeur::c);
}

int main() {
    std::stack<int> s;
    std::deque<int> &adapted = getAdapted(s);
    output(adapted); // print the stack...
}

No casting or type punning involved. It takes a pointer to a protected member of std::stack<int> through a class derived from it where that member name is public, so the compiler allows this. Then it uses it on a std::stack<int> object, which is allowed too.

半衾梦 2024-07-24 02:55:31

我就遇到过这种情况,因为有一个非常蹩脚的源代码控制系统,对于旧版本的应用程序来说,更改头文件几乎是不可能的。

如果某些情况你只需要进行黑客攻击。

在需要访问私有数据成员的源文件中,您可以将其作为第一行:

#define private public
#define protected public

并访问您想要的任何内容。

I have had this happen to me since there was a very crappy source control system in place where for old versions of the application making changes to header files was pretty much impossible.

If some cases you just need to do a hack.

In the source file from which you need to access the private data member you can put in this as a first line:

#define private public
#define protected public

and access anything you want.

倾城泪 2024-07-24 02:55:31

不,你所做的是纯粹的邪恶。

No. What you are doing is Pure Evil.

葬心 2024-07-24 02:55:31

“永不说永不”。 我确信在宇宙的某个地方,有一种情况会迫使你不得不这样做……

但如果我不得不这样做,我肯定会感到畏缩。 在扣动扳机之前,您确实需要针对您的情况获得大量意见。 您能否描述一下您的具体情况,也许我们可以看看它是否有意义或者可能存在哪些更好的替代方案?

回应评论/问题——
定义“权限”——机构权限? 这听起来不像是一个编程问题,而是与任何主张该许可的人交谈的问题。 也许这更多的是一个政治问题而不是技术问题? 再说一遍,我认为我们需要更多细节——即使这在某种程度上与局势的政治有关。 但是,这可能会或可能不会被视为超出网站的范围。

"Never say never". I'm sure somewhere in the universe, there's a situation that will force you to have to do this...

But I certainly would cringe if I had to do it. You truly need get lots of opinions on your situation before pulling the trigger. Can you describe your specific situation and maybe we could see if it makes sense or what better alternatives might exist?

In response to comment/question--
Define "permissions" -- institutional permission? That sounds like not a programming problem, but something to talk to whoever is asserting said permission. Maybe this is more of a political issue than a technical one? Again, I think we need more specifics--even if it was somewhat about the politics of the situation. That may or may not be deemed out of scope for the website, however.

辞别 2024-07-24 02:55:31

如果您迫切需要这样做,请忘记强制转换 - 只需修改头文件中的类声明:

class A {
  private:
    int x;
};

将其更改为:

class A {
  public:
    int x;
};

就可以了。 好吧,也许“好”这个词不太合适。

If you feel the urge to do this, forget casting - just modify the class declaration in the header file:

class A {
  private:
    int x;
};

change that to:

class A {
  public:
    int x;
};

and you are good to go. Well, perhaps "good" is not quite the right word.

野却迷人 2024-07-24 02:55:31

这是道德的,但通常是大量肮脏的代码,与未定义的行为和不可移植性相邻。 仅在绝对必要时才这样做。

It's ethical, but it's usually lots of dirty code neighbouring with undefined behaviour and unportability. Do it only if you absolutely have to.

流殇 2024-07-24 02:55:31

啊,抽象——没有它你就活不下去,但有时处理起来却很痛苦:)

无论如何,抛开道德不谈,如果类的“所有者”决定改变内部实现,或者简单地颠倒顺序,该怎么办?私有数据成员?

Ah, abstraction - you can't live without it and yet it is so painful to deal with sometimes :)

Anyway, ethics aside, what if the "owner" of the class decides to change the internal implementation, or simply reverses the order of the private data members?

帅气称霸 2024-07-24 02:55:31

唯一的“道德”问题是你对那个可怜的混蛋所做的事情,他将不得不弄清楚并维护你的代码。

私人会员就是这样。 他可能,而且很可能有一天会改变该成员。 当这种情况发生时,您甚至可能没有注意到,因为很可能仍然有记忆,只是不是您期待的成员。 该死的,当你的代码运行时,几乎任何你能想象到的几乎不可能的事情都可能开始发生。 怎么会有人能够调试它呢?

The only "ethical" problem is what you are doing to the poor bastard who is going to have to figure out and maintain your code.

Private members are just that. He may, and most likely will, one day change that member. When that happens, you might not even notice as there most likely will still be memory there, just not the member you were expecting. Damn near any nearly impossible thing you can imagine might then start happening when your code is run. How is anybody ever going to be able to debug that?

丑疤怪 2024-07-24 02:55:31

简单的回答:不。

这是不道德的,并且在某些时候会变成维护噩梦。 库的内部私有成员可以更改和破坏您的代码。 库的开发人员不需要知道(也不想)您违反了封装。

类的方法通常具有不变量,有时不会记录这些不变量,但从外部访问和更改值可能会破坏这些不变量。 举个例子,如果您将向量中的保留空间更改为更高的值,则向量在填充现有空间之前不会分配新空间,并且在触及未分配的内存之前不会发生这种情况:您的应用程序将崩溃。

如果属性是私有的,那么它不是供你使用的,只供类本身或了解该成员、如何使用它、如何不破坏它的类的朋友使用。 如果程序员希望你更改该字段,那么它将是公开的。

Simple answer: No.

It is not ethical and it will turn into a maintenance nightmare at some point. The internal private members of a library can change and break your code. Developers of the library do not need to know (nor want to) that you are violating the encapsulation.

Classes usually have invariants over their methods that some times will not be documented, but accessing and changing the values from the outside can break those invariants. As an example, if you change the reserved space in a vector for a higher value, the vector will not allocate new space until it has filled the existing and that won't happen before hitting unallocated memory: your application will crash.

If the attribute is private, it is not for you to use it, only for the class itself or the the class' friends that know about the member, how to use it, how not to break it. If the programmer wanted you to change the field, it would be public.

放低过去 2024-07-24 02:55:31

我认为这个课程是您正在从事的项目的一部分。

这里存在一个道德问题:
如果在您的公司中,您将代码的所有权视为神圣的。 或者最糟糕的是,您不允许修改不属于您的代码。 是的,您可能会伤害维持该类别的人的感情。 或者如果他的薪水与他的代码有关,就生气他。
所以最好的办法就是向他寻求任何帮助,以及一些建议,例如。 添加 getter 函数或将私有更改为公共 - 所有这些都基于您使用新代码的直觉。

你提到的黑客实际上是床上练习。 如果无法修改该代码,维护者就不会更改任何内容。 考虑使用适配器设计模式。

I assume that this class is part of project you are working on.

There is one ethical problem here:
If in your company you see ownership of code as sacrum. Or worst you are disallowed to modify code that is not yours. Yes You may hurt feeling of person that maintain that class. Or angry him if his salary is related to his code.
so best is just to ask him for any help, and few suggestions eg. add getter function or change private to public - all based on your intuition of using that new code.

Hack that you have mention is really bed practice. If cant modify that code and maintainer dont wont to change anything. Consider using adapter design pattern.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文