C++:允许访问类的受保护成员而不是私有成员

4
我知道您可以通过继承实现此功能,但是继承只适用于 "is a" 情况。我也知道有友元类,但它们允许访问私有成员。 是否有任何方法可以做到这一点(允许访问受保护的类成员,但不包括私有成员)? 重新表达问题,我有类1和类2。我希望类2可以访问类1的受保护和公共成员,但不能访问其私有成员。如何实现?

1
在“有没有办法做到这一点?”中,你所指的“this”是什么? - Boris Strandjev
我应该更清楚地表达。我指的是这个问题:“允许访问类的受保护成员而不是私有成员”。 - Jalfor
至于允许谁访问,我是指第一类。 - Jalfor
3个回答

阿里云服务器只需要99元/年,新老用户同享,点击查看详情
5
这可能不够优雅,但对您有用:
class B;

class A {
protected:
    int x;
private:
    int y;
};

class A_wrapper : public A {
    friend B;
};


class B {
public:
    A_wrapper a;
    int foo() {
        a.x;   // Ok
        a.y;   // Compiler error!
    }
};

确实很棘手,要做到一些干净的事情。protected 仅适用于基类子对象的成员,而不适用于同类型的其他对象的成员。(即只能通过 this - MSalters
但你认为这样做是个好主意吗?不是针对你的具体实现,而是这个总体想法。 - juanchopanza
这看起来是最干净和最简单的方法,所以我会接受它,尽管从周围的一些评论中,我觉得我可以尝试通过移动一些其他变量来使其工作,这样我就不必这么做。 - Jalfor
@juanchopanza:我想这取决于情况。如果需要这样做,那么很可能需要重新设计(尽管并不总是有这种奢侈的条件!)。 - Oliver Charlesworth
仅仅因为一种语言阻止你做某些事情,并不意味着这是设计问题。这可能只是语言的限制。例如,“友元”关系是非黑即白的。你不能只给予访问你私有/受保护内容的部分权限。是的,你可以通过将一个类拆分成两个或更多部分来绕过这个问题。从工程角度来看,这似乎是一种“更干净”的方式,但这会产生大量样板代码。如果你有太多的样板代码,那么无论从工程角度看起来多么正确,使用起来都会变得困难。 - CygnusX1
@CygnusX1 - 五年过去了,我绝对同意这种观点(即语言限制不等于设计问题),总的来说 :) 话虽如此,即使现在,如果没有进一步的上下文,我可能仍然会建议OP是一个XY问题 - Oliver Charlesworth

2

很久以前,在这个网站上,我提出了一个使用 Key 的方案。这个想法是,主类记录哪些接口可以公开访问,哪些需要密钥,并授予需要它的人密钥的友好权限。

class Key { friend class Stranger; Key() {} ~Key() {} };

class Item {
public:
    void everyone();

    void restricted(Key);
private:
};
现在,只有Stranger可以使用restricted方法,如下所示:
class Stranger {
public:
    void test(Item& i) {
        Key k;
        i.restricted(k);
    }

    Key key() { return Key(); }

    Key _key;
};

class Other {
    void test(Item& i) {
        Stranger s;
        i.restricted(s.key()); // error: ‘Key::~Key()’ is private
                               // error: within this context
    }

    void test2(Item& i) {
        Stranger s;
        i.restricted(s._key); // error: ‘Key::~Key()’ is private
                              // error: within this context
                              // error:   initializing argument 1 of ‘void Item::restricted(Key)’
    }
};

这是一个非常简单的方案,它允许比完全的友谊更细致的方法。

该内容涉及IT技术。

1

Oli提供了一个更接近的解决方案(+1),但你也可以使用选择性好友的方法来处理:

#include <iostream>

class t_thing;

class t_elsewhere {
public:
    void print(const t_thing& thing);
};

class t_thing {
public:
    class t_selective_friend {
        static int Prot(const t_thing& thing) {
            return thing.prot;
        }

        friend class t_elsewhere;
    };
public:
    int publ;
protected:
    int prot;
protected:
    int priv;
};

void t_elsewhere::print(const t_thing& thing) {
    std::cout << t_thing::t_selective_friend::Prot(thing) << std::endl;
}

int main() {
    t_thing thing;

    thing.publ; /* << ok */
    thing.prot; /* << error */
    thing.priv; /* << error */
    t_elsewhere().print(thing); /* << ok */
    return 0;
}
有时候冗长和控制是好的...

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,