C++ 类具有不同的访问权限:对多个对象只读,对特权对象可写

C++ 类具有不同的访问权限:对多个对象只读,对特权对象可写,c++,oop,design-patterns,private,derived-class,C++,Oop,Design Patterns,Private,Derived Class,我在一些类中分组了大量字符串,所有字符串都分组在最后一个大类中。该类必须由另一个类填充,并且它的不可变内容必须公开给某些客户端。(当然,这些类更复杂,这是一个简化的示意图表示。) 解决方案1: class A { friend class M; private: B m_b; C m_c; D m_d; public: const B& GetB() const { return m_b;} const C& GetC() const

我在一些类中分组了大量字符串,所有字符串都分组在最后一个大类中。该类必须由另一个类填充,并且它的不可变内容必须公开给某些客户端。(当然,这些类更复杂,这是一个简化的示意图表示。)

解决方案1:

class A
{
friend class M;

private:
    B m_b;
    C m_c;
    D m_d;

public:
    const B& GetB() const { return m_b;}
    const C& GetC() const { return m_C;}
    const D& GetD() const { return m_D;}

private:
    B& GetB() { return m_b;}
    C& GetC() { return m_C;}
    D& GetD() { return m_D;}
}
其中,B类似于:

class B
{
friend class M;

private:
    std::string m_camel;
    std::string m_pink;
    std::string m_vandergraaf;

public:
    const std::string& Camel() const { return m_camel;}
    const std::string& PinkFloyd() const { return m_pink;}
    const std::string& VanDerGraafGenerator() const { return m_vandergraaf;}

private:
    void SetCamel(const char* prog) { m_camel = prog;}
    void SetPinkFloyd(const char* prog) { m_pink = prog;}
    void SetVanDerGraafGenerator(const char* prog) { m_vandergraaf = prog;}
}
对于
受保护的
,避免使用
朋友
的更好的解决方案是将写访问类公开给M,将基类以只读方式公开给世界

解决方案2:

class A
{
protected:
    B m_b;
    C m_c;
    D m_d;

public:
    const B& GetB() const { return m_b;}
    const C& GetC() const { return m_C;}
    const D& GetD() const { return m_D;}
}

//  only visible to M
class A_Write: public A
{
public:
    B& GetB() { return m_b;}
    C& GetC() { return m_C;}
    D& GetD() { return m_D;}
}
B也一样,也许吧。这不是一个很好的解决方案,因为客户端也可以派生自己的类

解决方案3是一个更好但更具约束性的变体:

class A
{
private:
    const B m_b;
    const C m_c;
    const D m_d;

public:
    const B& GetB() const { return m_b;}
    const C& GetC() const { return m_C;}
    const D& GetD() const { return m_D;}

protected:
    A(const B& b, const C& c, const D& d): m_b(), m_c(c), m_d(d) {}
}

//  only visible to M
class A_Write: public A
{
public:
    A_Write(const B& b, const C& c, const D& d): A(b, c, d) {}
}
我的首选解决方案是4,即。。。3但B、C、D作为简单的
struct
s而不是
class
es。所以M可以直接在B,C,D中做它想做的任何事情,然后构造a_写


有更好的想法吗?

一种可能的方法是使用一个减少类接口的代理。
M
将实例化/接收
S
的实例(以便能够使用其接口对其进行修改),但它将向读取器返回一个代理
P
(读取器将无法对其进行修改)。
下面是一个简单的例子:

struct S {
    void value(int v) noexcept { t = v; }
    int value() const noexcept { return t; }
private:
    int t{0};
};

struct P {
    P(S& s): b{s} { }
    int value() const noexcept { return b.value(); }
private:
    S& b;
};

int main() {
    // the class: full interface
    S s;
    // the proxy: reduced interface
    P p{s};
}

这就是代理可以用来降低界面可见性的原因。你试过吗?你是说皮姆普尔吗?这个:?你是说虚拟的吗?我的第一个想法是这对我的案子来说太重了。我现在得睡觉了,再见!请你在回答中阐明你的想法好吗?使用某些类模式?我喜欢您的解决方案,但我认为P可以返回对S(和其他)的常量引用,以避免为所有成员编写“代理”函数(值)。第二种解决方案是我的公司首选的,尽管您的解决方案更好,因为它将类分开。