Allowing a “friend” class to access only some priv

2019-01-17 06:25发布

Suppose I have three C++ classes FooA, FooB and FooC.

FooA has an member function named Hello, I want to call this function in class FooB, but I don't want class FooC be able to call it. The best way I can figure out to realize this is to declare FooB as a friend class of FooA. But as long as I do this, all FooA's private and protected members will be exposed which is quite unacceptable to me.

So, I wanna know if there is any mechanism in C++(03 or 11) better than friend class which can solve this dilemma.

And I assume it will be nice if the following syntax is possible:

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
    }
};

标签: c++ friend
7条回答
ら.Afraid
2楼-- · 2019-01-17 06:53

I think you can use Attorney-Client here.

In your case example should be like this

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*/
    }
};
查看更多
混吃等死
3楼-- · 2019-01-17 06:55

There's nothing to make a class a friend of one specific function, but you can make FooB a friend of a "key" class with private constructor, and then have FooA::Hello take that class as an ignored parameter. FooC will be unable to provide the parameter and hence can't call Hello:

Is this key-oriented access-protection pattern a known idiom?

查看更多
欢心
4楼-- · 2019-01-17 07:04

The safest solution is to use another class as the "go-between" for your two classes, rather than make one of them a friend. One way to do this is suggested in the answer by @ForEveR, but you can also do some searching about proxy classes and other design patterns that can apply.

查看更多
祖国的老花朵
5楼-- · 2019-01-17 07:10

The whole idea of friend is to expose your class to a friend.

There are 2 ways you could be more specific about what you expose:

  1. Inherit from FooA, that way only protected and public methods are exposed.

  2. Only befriend a certain method, that way only that method will have access:

.

 friend void FooB::fun();
查看更多
ら.Afraid
6楼-- · 2019-01-17 07:12

No, and this is not really a limitation. To my mind, the limitation is that friend — a blunt weapon for hacking around design flaws — exists in the first place.

Your class FooA has no business knowing about FooB and FooC and "which one should be able to use it". It should have a public interface, and not care who can use it. That's the point of the interface! Calling functions within that interface should always leave the FooA in a nice, safe, happy, consistent state.

And if your concern is that you might accidentally use the FooA interface from somewhere you didn't mean to, well, simply don't do that; C++ is not a language suited to protecting against these kinds of user errors. Your test coverage should suffice in this case.

Strictly speaking, I'm sure you can obtain the functionality you're after with some ghastly complicated "design pattern" but, honestly, I wouldn't bother.

If this is a problem for the semantics of your program's design, then I politely suggest that your design has a flaw.

查看更多
Root(大扎)
7楼-- · 2019-01-17 07:12

You'll need inheritance. Try this:

// _ClassA.h
class _ClassA
{
  friend class ClassA;
private:
  //all your private methods here, accessible only from ClassA and _ClassA.
}

// ClassA.h
class ClassA: _ClassA
{
  friend class ClassB;
private:
  //all_your_methods
}

This way you have: ClassB is the only one to be able to use ClassA. ClassB cannot access _ClassA methods, that are private.

查看更多
登录 后发表回答