让一个方法只能由一个独特类型的类使用

时间:2012-01-21 18:08:29

标签: c++ encapsulation

我目前正在寻找一种适当的方法来限制特定类型的类使用方法。更清楚的是,情况如下:

我有一个专门用于服务器网络的课程(让我们称之为ClientSession)。客户端连接到服务器后,有30秒的时间进行身份验证,或者服务器将关闭连接。

身份验证由服务器上的另一个类处理(让我们称之为Authenticator),这应该是警告' ClientSession客户端验证成功,30秒计时器可以取消。

问题是,这需要Authenticator来调用ClientSession的公共方法。但是我不希望任何人都能调用这种方法。

总结一下,我希望Authenticator成为唯一能够调用ClientSession::clientAuthSuccessful()方法的类。

我已经研究过两件事:

  • 朋友方法,但我不希望Authenticator能够通过朋友方法访问所有私有方法和属性或ClientSession
  • 访客设计模式,但它似乎并没有完全符合我的要求(除非我误解了它的用法)。

还有其他方法可以有这样的特定限制吗?还是一个干净的选择?

5 个答案:

答案 0 :(得分:2)

定义一个接口AuthenticatorListener,其中定义了clientAuthSuccessful()方法(纯虚拟)。

ClientSession私下继承AuthenticatorListener并私下实施该方法。

然后将ClientSession实例传递给Authenticator

现在没有其他类可以访问该方法。并且Authenticator未与ClientSession耦合,只与适当隔离的界面耦合。

答案 1 :(得分:1)

这样做没有干净的方法,没有。您可以使用朋友类或公共方法。

没有干净的方式并不意味着不可能。我永远不会写这样的代码,你也不会这样做,但以下内容确实符合要求:

class Lock
{
    friend class B;
private:
    Lock() {};
};


class A
{
public:
    A() {}
    void foo(Lock x){}
};

class B
{
    void foo()
    {
        Lock l;
        A a;
        a.foo(l);
    }
};

由于class B是唯一可以创建Lock个实例的类,而A::foo需要Lock个实例作为参数,因此只能由{{1}调用}}

不要这样做。我建议在标题中添加注释和文档。

答案 2 :(得分:1)

有一种更简单的方法。只需将一些特殊用途的代码从ClientSession传递到Authenticator即可。您可以使用函数指针,函数对象或lambda函数来实现此目的。

class ClientSession
{
public:
    void startSession ( Authenticator& authenticator )
    {
        // pass function pointer to method to call when
        // the timeout for authentication has elapsed.
        authenticator.start(this, &ClientSession::warnThat30SecsHasPassed);

        // alternative syntax, using new lambda function syntax,
        // which will end up reducing coupling between the two classes.
        authenticator.start([this](){ warnThat30SecsHasPassed() });
    }
private:
    void warnThat30SecsHasPassed () { ... }
};

class Authenticator
{
public:
    // classic way.
    void start ( ClientSession * session, void(ClientSession::*callback)() );

    // using new syntax.
    void start ( std::function<void()> callback );
}

答案 3 :(得分:0)

您可以创建ClientSession朋友和朋友Authenticator

的代理类

答案 4 :(得分:0)

当遇到问题时,人们经常会想到如何解决问题,并将精力放在如何实施该解决方案上。有时,更好地重新审视问题并考虑其他解决方案。

例如,不要让Authenticator尝试通知传递给它的ClientSession(或者更好的方法是,通过调用传递给它的某种回调 ),让ClientSession(或其他一些对象/线程)调用像Authenticator::waitForAuthentication(int timeout)这样的方法呢?


编辑:我想我会详细说明回调概念。关键是Authenticator不需要知道ClientSession类来完成它的工作;它只需要知道调用某个函数或其他可调用函数。

因此,您编写Authenticator以使方法接受正确签名的某个std::function对象,并使ClientSession(或其他)创建合适的内容以传入。它可能是一个类似于Luchian Grigore所建议的特殊功能对象。也许它是一个稍微更通用的对象,或者可能是通过引用ClientSession对象的私有部分来初始化的对象。或者它是一个lambda,如果你可以使用C ++ 11。

那就是说,我怀疑使用waitForAuthentication方法(或完全不同的方法)很可能是你真正想要的应用程序。