允许"朋友"类仅访问某些私有成员

Arc*_*her 33 c++ friend

假设我有三个C++类FooA,FooB和FooC.

FooA有一个名为的成员函数Hello,我想在类FooB中调用这个函数,但我不希望类FooC能够调用它.我能想出来实现这一点的最好方法是将FooB声明为FooA的朋友类.但只要我这样做,所有 FooA的私人和受保护成员都将被曝光,这对我来说是非常不可接受的.

所以,我想知道C++(03或11)中是否有任何机制比friend类可以解决这个难题更好.

我认为如果可以使用以下语法会很好:

class FooA
{
private friend class FooB:
    void Hello();
    void Hello2();
private:
    void Hello3();
    int m_iData;
};

class FooB
{
    void fun()
    {
        FooA objA;
        objA.Hello()  // right
        objA.Hello2() // right
        objA.Hello3() // compile error
        ojbA.m_iData = 0; // compile error
    }
};

class FooC
{
    void fun()
    {
        FooA objA;
        objA.Hello()  // compile error
        objA.Hello2() // compile error
        objA.Hello3() // compile error
        ojbA.m_iData = 0; // compile error
    }
};
Run Code Online (Sandbox Code Playgroud)

Ste*_*sop 29

没有什么可以使一个类成为一个特定函数的朋友,但你可以FooB使用私有构造函数建立一个"key"类的朋友,然后FooA::Hello将该类作为一个被忽略的参数.FooC将无法提供参数,因此无法调用Hello:

这种面向密钥的访问保护模式是一种已知的习惯用法吗?


For*_*veR 24

我想你可以在这里使用律师 - 客户.

在你的情况下,例子应该是这样的

class FooA
{
private:
    void Hello();
    void Hello2();
    void Hello3();
    int m_iData;

    friend class Client;
};

class Client
{
private:
   static void Hello(FooA& obj)
   {
      obj.Hello();
   }
   static void Hello2(FooA& obj)
   {
      obj.Hello2();
   }
   friend class FooB;
};

class FooB
{
    void fun()
    {
        FooA objA;
        Client::Hello(objA);  // right
        Client::Hello2(objA); // right
        //objA.Hello3() // compile error
        //ojbA.m_iData = 0; // compile error
    }
};

class FooC
{
    void fun()
    {
        /*FooA objA;
        objA.Hello()  // compile error
        objA.Hello2() // compile error
        objA.Hello3() // compile error
        ojbA.m_iData = 0; // compile error*/
    }
};
Run Code Online (Sandbox Code Playgroud)


rol*_*vax 5

您可以通过从接口类继承类来将类的接口部分公开给指定的客户端。

class FooA_for_FooB
{
public:
    virtual void Hello() = 0;
    virtual void Hello2() = 0;
};

class FooA : public FooA_for_FooB
{
private: /* make them private */
    void Hello() override;
    void Hello2() override;
private:
    void Hello3();
    int m_iData;
};

class FooB
{
    void fun()
    {
        FooA objA;
        FooA_for_FooB &r = objA;
        r.Hello()  // right
        r.Hello2() // right
        objA.Hello3() // compile error
        objA.m_iData = 0; // compile error
    }
};

class FooC
{
    void fun()
    {
        FooA objA;
        objA.Hello()  // compile error
        objA.Hello2() // compile error
        objA.Hello3() // compile error
        objA.m_iData = 0; // compile error
    }
};
Run Code Online (Sandbox Code Playgroud)

在这里,访问控制由基类增强FooA_for_FooB。通过类型的引用FooA_for_FooBFooB可以访问内部定义的成员FooA_for_FooB。但是,FooC无法访问这些成员,因为它们已在 中被覆盖为私有成员FooAFooA_for_FooB您的目的可以通过不使用中的类型FooC或除 之外的任何其他地方的类型来实现FooB,无需太注意即可保留。

这种方法不需要friend,使事情变得简单。

类似的事情可以通过将基类中的所有内容设置为私有,并有选择地将某些成员包装并在派生类中公开为公共来完成。不过,这种方法有时可能需要丑陋的沮丧。(因为基类将成为整个程序中的“货币”。)