【问题标题】:Hide methods of instance returned to caller隐藏返回给调用者的实例方法
【发布时间】:2018-06-06 10:04:42
【问题描述】:

在对象 A 中有一个类型为 B 的对象数组。B 类有方法 B1,B2,...B10

我希望对象 A 有一个方法,该方法返回指向 B 类型对象的指针,但只公开方法 B9-B10。调用者不应该知道方法 B1-B8

当返回指向 B 类型对象的指针时,如何隐藏方法 B1-B8?我正在使用 C++

更新:

对象 A 需要访问 B 的所有方法,但 A 只会将方法 B9-B10 暴露在 A 之外。

【问题讨论】:

  • 你使用什么语言?
  • 将它们设为私有?
  • 你有几种方法可以做到这一点:将继承公开,use Base::B9 在私有范围内,使用私有继承并在公共范围内公开B1-B8,或者让类@ 987654323@ 成为私人成员并在B1-B8 周围编写内联包装器。请注意,最后一个可能会阻止空基优化,而公共继承将允许强制转换为基类。

标签: c++ class wrapper


【解决方案1】:

这似乎是Proxy Pattern. 的位置。ProxyB 类只会公开 B9 - B10。

但是,在我看来,如果方法 B9 和 B10 足够了,那么它们会创建自己的独特接口。这两个方法应该是它们自己的类接口。如果 B 由具有方法 B1-B8 的 BA 和具有方法 B9-B10 的 BB 组成,那么您可以只返回一个指向 BB 的指针。

【讨论】:

  • 如果使用代理模式,如果隐藏成员函数从根本上来说很重要,我强烈推荐私有继承。但是在公共范围内使用using B::B1 很容易做到这一点。可能是最好的解决方案。
  • 我认为这与我想要的很接近,但在这个概念上有点困难。如果 A 需要访问 B 的所有方法,那么它不能只创建 Bproxy 对象。如果 A 只会创建和公开 Bproxy,它如何访问 B 的所有方法? A 是否应该创建 2 个列表:一个 B 对象列表和第二个 Bproxy 对象列表(其中包含指向 B 的指针并提供调用 B 方法的方法子集),以便 A 可以访问 B 的所有方法,但只返回 Bproxy 对象来电者?能举个小例子吗?
  • 我是否创建派生自 B_1_to_8 和 B_9_to_10 的对象 B?两个基础对象都需要访问相同的成员变量。我不确定如何实现这一点。我认为这真的很接近我想要的。
【解决方案2】:

我能想到的一种方法是创建另一个名为C 的类,其构造函数使用类B 的对象,并且只提供方法B9 和B10。

class C
{
    private:
        B B_object;
    public:
        C(B i_obj){
            B_object = i_obj;
        }
        void B9_wrapper(){
            B_object.B9();
        }        
        void B10_wrapper(){
            B_object.B10();
        }
}

然后您的 A 方法返回一个指针(我们将其命名为 a_method),必须将 B 的对象转换为 C 的对象,然后返回指向后一个对象的指针:

class A{
    private:
        B arr[10]; // array of objects of B
    public:
        void method_a(){
            // let arr[3] be the object you want to return a pointer of
            C result {arr[3]};
            return &result;
        }

希望对你有所帮助。

【讨论】:

    【解决方案3】:

    您在这里有很多不同的选择,我们应该使用代理模式,除了其中一个之外,所有这些都存在陷阱。

    基类

    这里我们有一个理论上的、平凡的、空的基类,它有 4 个成员函数。我们要公开其中的 2 个。

    class Base
    {
    public:
        void b1() {};
        void b2() {};
        void b3() {};
        void b4() {};
    };
    

    公共继承,隐藏方法

    如果我们有很多方法希望公开,但只有少数希望隐藏,那么使用公共继承可能很诱人,然后在派生类中隐藏一些方法。例如:

    class Derived1: public Base
    {
    public:
        char* x() { return x_; }
    
    private:
        using Base::b3;
        using Base::b4;
    
        char x_[2];
    };
    

    我建议不要这样做,因为它允许基类使用 static_cast,这将允许任何人安全地将该类视为基类,从而有效地使派生类成为一个弱建议,充其量。

    私有继承,公开方法

    这是我最喜欢的一组,因为它阻止 static_cast 访问基类,并且会依赖隐式、reinterpret_cast 或 C 风格的强制转换尝试访问基类(它仍然由标准,但是一个更强有力的建议)。

    class Derived2: private Base
    {
    public:
        using Base::b1;
        using Base::b2;
        char* x() { return x_; }
    
    private:
        char x_[2];
    };
    

    包装器/适配器

    最后一次尝试阻止对基类的所有访问,因此提供了最有力的保证,但这样做的代价是增加了类大小(仅当基类为空时):

    class Wrapper1
    {
    public:
        void b1() { b_.b1(); }
        void b2() { b_.b2(); }
        char* x() { return x_; }
    
    private:
        Base b_;
        char x_[2];
    };
    

    总结

    以上各有各的优点,各有各的缺陷。我建议使用第二个或第三个选项,包装现有类并提供一个公共接口,在合理范围内只能与所需接口一起使用。

    【讨论】:

    • 我喜欢从基础派生的想法,但是,A 需要访问 B 的所有方法(因此它不能实例化从 B 对象派生)。 A 只需要暴露每个 B 的一些方法,而隐藏其余的。
    猜你喜欢
    • 2013-10-17
    • 2011-01-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多