【问题标题】:Friend class accessing protected member only C++仅访问受保护成员的朋友类 C++
【发布时间】:2020-08-18 16:29:56
【问题描述】:
class A;

class B {
private:
    int x = 3;
protected:
    int y = 4;
public:
    int k = 5;
};

我希望A 能够访问Bpublicprotected 成员,但不能访问其private 成员。

我不希望 A 派生自 B

-在我的程序中,我有一个类A,它操作类B。我已经使用这两个类构建了一个系统,因此B 应该只能通过Aprotected 函数来操作Aprivate 变量。

最优雅的方法是什么?以这种方式暴露变量是一种好习惯吗?

【问题讨论】:

  • 你为什么不想从B 派生A ?这正是protected 成员访问的功能
  • @Odysseus 但是每个A 实例都是B 实例。可能有很多原因表明这是不可取的。
  • 这听起来像XY problem。当然,有一种更好的方法可以对您尝试建模的系统进行建模,而不会笨拙地耦合这两个类。 C++ 提供了两种耦合类的方法:继承(B 确实是 A,因此可以看到这一切)和友谊(A 完全信任 B)。即使这两者都应该谨慎使用(紧密耦合),像这样更复杂的可见性约束可能只会让人感到困惑。
  • @Miguel 是的——但这仍然是protected 的目的。所以重新安排课程对我来说似乎是合理的
  • @Odysseus 哺乳动物可以衍生自呼吸系统类;这并不意味着哺乳动物本身就是一个呼吸系统

标签: c++ friend


【解决方案1】:

我能想到的唯一解决方案是利用朋友关系的非关联性。如果您将 B 的私有成员包含在另一个类中并将 B 设为其朋友,它会起作用。

这是我所说的一个例子。

class B{
    private:
        class private_of_B{
        private:
            friend class B;
            int x = 3;
        };
        private_of_B private_members;
        friend class A;
    
    protected:
        int y = 4;
    
    public:
        int k = 5;
};
class A{
    public:
        void f(B& b) const{
            cout << b.y << endl;
            // good
            cout << b.k << endl;
            // good
            cout << b.private_members.x << endl;
            // error
        }
};

无论如何,这种解决方法似乎是糟糕的设计......也许你能做的最好的事情就是重新设计你的类架构。

另外,您可能会发现this question 很有用。

【讨论】:

  • 基类super_B是B类的成员,所以A类可以访问B类对象的成员。
  • super_B 不是B 的成员,它是它的父类,所以类A 不允许访问它的任何非公共成员。
  • 运行这个程序。 #include A 类;类 super_B{ 受保护:int x = 3; }; B 类:public super_B{ 保护:朋友类 A;整数 y = 4;公共:int k = 5; };类 A { public: void f( const B &b ) const { std::cout
  • 我更改了答案并对其进行了测试,所以它现在可以工作了。但正如我所说,我会建议重新设计。
【解决方案2】:

如果你不想改变 B,你可以创建一个代理类:

class B {
private:   
  int x = 3;
protected: 
  int y = 4;
public:    
  int k = 5;
};

class C : public B {
  friend class C_Proxy;
  // constructors...
};

class C_Proxy {
public:
  friend class A;
  C_Proxy(C& c) : y(c.y), k(c.k) { }
private:
  int& y;
  int& k;
}

(您也可以安排 C_Proxy 来处理代理常量 B,但这不是问题的重点。)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-13
    • 1970-01-01
    • 2014-02-20
    • 1970-01-01
    • 2019-08-08
    • 1970-01-01
    相关资源
    最近更新 更多