【问题标题】:Granting access on a function to another class without exposing it将一个函数的访问权限授予另一个类而不暴露它
【发布时间】:2018-05-31 05:59:24
【问题描述】:

我有一门课,我们叫它Person

class Person{
private:
    void move(x,y,z);
}

我还有一个班级叫PersonController

class PersonController{
public:
    void control(){
        while(some_thing){
             //do some calculations
             controlled_person_->move(some_values); //Wrong Accessing to a private member
        }
    }
private:
    Person* controlled_person_;
}

PersonPersonController 都是我正在设计的库的公共接口的一部分。

我希望PersonController 能够从Person 呼叫move。但是,我不希望任何人从公共界面访问此功能(move)。

解决问题的简单方法是添加友谊,以便PersonController 可以访问Person 的私人成员。然而,据我所知,friend 关键字并没有被引入来解决这类问题,在这里使用它是一种不好的做法。

  • 这是正确的吗?我应该在这里避免friend 吗?
  • 这是否意味着我的设计被破坏了?
  • 还有其他建议吗?

【问题讨论】:

  • 这些类是同一个逻辑接口的一部分吗?意思是,没有PersonController,你就不能拥有Person
  • 不,你可以有一个Person 没有PersonController
  • 您的前两个问题以 SO 的格式无法回答。你应该避免它吗?谁知道。这可能是最简单和最正确的解决方案,具体取决于您的整个设计。请允许我颠倒这个表格。 Person 里面有什么东西不能让PersonController 接触吗?
  • 当然可以。例如,人名是不应该被触及的东西。 PersonController 只是一个运动控制器。
  • @HumamHelfawi,我认为您正在尝试使用friendship 克服设计错误。我猜函数Person::move 将一个对象移动到一个新位置。这意味着 Person 有位置。理想情况下,这听起来不像Person 的内在数据。你能解耦这些概念,以便不同的类负责跟踪Persons 的位置吗?您可以使用该类来移动Person

标签: c++ design-patterns


【解决方案1】:

这正是朋友所要解决的问题。如果您的设计需要友谊,应该尽量减少友谊,但没有理由不使用它。

我看到不使用friend很像一直不喜欢'goto',有时使用它会使设计更简洁。

【讨论】:

    【解决方案2】:

    是的,您的设计不正确。

    类是数据结构的扩展概念:与数据结构一样,它们可以包含数据成员,但也可以包含作为成员的函数。 You can read more here

    所以PersonController(如果它只控制人类)不应该是一个类,因为它不是数据结构的概念检查是否可以合并它们或设计另一种方式。

    有很多方法可以做到。如果你想像现在一样设计它,你可以为你的函数使用受保护的访问控制器并创建派生类,但这又不是一个好的设计。

    你也可以在这里使用友元函数,但它不再是一个面向对象的概念(但最简单的方法)。

    你应该重新考虑你的设计如果你想设计它 OO。因为在面向对象编程中你不能从其他类访问私有函数,它破坏了封装,所以 C++ 不会让你这样做。

    不过,您的问题也取决于意见。

    【讨论】:

    • 不知道为什么这个答案被否决了。我同意数据和作用于它的方法应该属于同一类型的论点。以“-er”结尾的类型名称是一种代码异味,表明过程式编程而不是面向对象的设计。
    • @MoonMoo 我也不确定 :))
    【解决方案3】:

    根据您在 cmets 中所说的,您似乎只对允许 PersonController 接触该成员函数感兴趣。做到这一点的唯一方法就是公开门,但要为其添加一个私钥:

    class Person{
    public:
        class MovePrivilege {
            move_privilege() = default; // private c'tor
            friend class PersonController; // only PersonController may construct this
        }; 
    
        void move(MovePrivilege, x,y,z);
    };
    
    class PersonController{
    public:
        void control(){
            while(some_thing){
                 //do some calculations
                 controlled_person_->move(MovePrivilege{} , some_values);
            }
        }
    private:
        Person* controlled_person_;
    };
    

    MovePrivilege 类型有一个私有 c'tor。所以它只能由它的朋友建造。并且拨打move也需要。所以虽然move 是公开的,但唯一可以调用它的类是MovePrivilege 的朋友。

    这实质上使您可以细粒度地控制谁可以调用移动。如果这很突兀并且您无法自行更改移动,则attorney client idiom 的变体可能是合适的。

    您确实可以选择。直接firend-ship 是最直接的工具。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-08-08
      • 1970-01-01
      • 1970-01-01
      • 2023-04-07
      • 2017-07-12
      • 1970-01-01
      • 2016-03-23
      • 2020-01-25
      相关资源
      最近更新 更多