繁体   English   中英

如何将类 A 的非常量公共成员 m 的访问限制为对另一个类 B 的常量访问,其中包含 A 作为非常量成员?

[英]How to restrict access to a non-const public member m of a class A to be const to a another class B, containing A as a non-const member?

晚上好!

我发现这个问题对其他人也很有趣。 所以我选择这个来最后问我关于堆栈溢出的第一个问题。 对这种情况的最低限度描述如下:

class A {
public:
    Type_m_first m_first;
    Type_m_second m_second;
}

class B { // shoud be const on a.m_first
private:
    A& a; 
public:
    B(A& a_) : a(a_) {};
}

编辑:A的成员设置为private并使用 getter 和 setter 不能解决我的问题。 但是,我希望有一个像这样简单的解决方案,因为由于我缺乏编程经验,我很可能会错过一些简单的东西。

现在,我需要的任何尚未将要实施的方法, B只具有const访问A.m_first同时具有非const访问A.m_second ,同样,我需要使用类型的东西任何其他代码B具有访问Ba时,访问限制相同。 当然,这是不可能的(至少从我卑微的角度来看)。

尽管如此,我的问题是:

如何在类B上强制执行对非const成员变量的访问的const限制?

编辑与私人m_firstm_second和一个getter和setter m_firstm_second的情况是一样的。 那么问题来了:如何限制B访问m_firstconst getter,拒绝B访问m_first的setter,同时允许B使用m_second的setter?


以上是问题。 然而,如果没有以下上下文,这个问题可能是不完整的,因为它说明了这个问题的重要性。 我面临的实际情况如下:

class A {
public:
    Type_m_first m_first;
    Type_m_second m_second;
public:
    // A lot of code.
private:
    // A lot of code.
}

class B { // shoud be const on a.m_first
private:
    A& a;
public:
    B(A& a_) : a(a_) {};
private: 
    // A lot of code, that I am supposed to move from somewhere else to here
    // or write myself.
public: 
    // A lot of code, that I am supposed to move from somewhere else to here
    // or write myself.
}

class C { // shoud be const on a.m_second
private:
    A& a;
public:
    C(A& a_) : a(a_) {};
private: 
    // A lot of code, that I am supposed to move from somewhere else to here
    // or write myself.
public: 
    // A lot of code, that I am supposed to move from somewhere else to here
    // or write myself.
}

/* 
 * A lot of other Code that is supposed to work with A, B and C. The following three
 * functions serve as an example. As you see, everything is manipulating essentially 
 * the same data from a.
 */ 

 void f(A& a, /* other args */ ) { /* ... */ }; 
 void g(B& b, /* other args */ ) { /* ... */ }; // shoud be const on b.a.m_first by design
 int h(C& c, /* other args */ ) { /* ... */ };  // shoud be const on c.a.m_second by design
 
 int main() {
     A a; 
     B b = B(a);
     C c = C(a);

     f(a, /* other args */ );
     g(b, /* other args */ );
     return h(c, /* other args */ );
 }
  

同样,我需要的任何尚未将要实现的方法B仅具有const访问A.m_first同时具有非const访问A.m_second 但是,对于类C我需要这正好倒过来:我需要的任何尚未将要实现的方法C只具有const访问A.m_second同时具有非const访问A.m_first 同样,任何使用BC类型的代码都应该有相应的访问限制。

当然,问题又来了:我为什么需要这个? 答案是,算法的逻辑结构将由这样的设计强制执行。 公开一切只是目前为止的一个问题,因为偶然忽略逻辑结构会导致难以发现代码中的错误,并且由于代码的复杂性,很难跟踪这些不是由设计强制执行的限制.

我想出的最佳解决方案 - 但尚未实现 - 是将代码复制到两个包装类:

class A_first {
public:
    const Type_m_first& m_first;
    Type_m_second& m_second;
    A_first(A&) ; m_first(const A.m_first), m_second(A.m_second) {};
public:
    // Same code as before.
protected:
    // Same code as before.
private:
    // Same code as before.
}

class A_second {
public:
    Type_m_first& m_first;
    const Type_m_second& m_second;
    A_first(A&) ; m_first(A.m_first), m_second(const A.m_second) {};
public:
    // Same code as before.
protected:
    // Same code as before.
private:
    // Same code as before.
}

这不是我们所希望的,因为随着时间的推移,代码会发生很多变化,并且跟踪三个类中的变化很容易出错。 我的问题是,在这种情况下该怎么办?

我非常怀疑这是否值得付出努力,但这可能适合您的需求:

而不是传递BCA的引用(这将授予他们对A无限制访问权限,如果我理解正确,这就是你的整个问题),只将访问器传递给两个成员。 这可能看起来像这样:

class B {
private:
    std::function<Type_m_first const&()> getConstFirst;
    std::function<Type_m_second&()> getNonConstSecond;
public:
    B(std::function<Type_m_first const&()> f1, std::function<Type_m_second&()> f2)
        : getConstFirst(std::move(f1)), getNonConstSecond(std::move(f2)) {};

    void someMethod() {
        getConstFirst() = abc; // this won't compile
        getNonConstSecond() = xyz; // this will
    }
}

C类似实现。

然后,使用通过引用捕获A实例的 lambda 将函数传递给BC的 c'tors:

A a; 
B b = B(
    [&a]() -> auto const& { return a.m_first; },
    [&a]() -> auto& { return a.m_second; }
    );
C c = C(
    [&a]() -> auto& { return a.m_first; },
    [&a]() -> auto const& { return a.m_second; }
    );

好吧,我必须承认,我只是略读了你的问题,所以我可能错过了一些细节。 但是返回const引用的 getter 不是您需要的吗?

class A {
private:
    Type_m_first m_first;
public:
    const Type_m_first & get_m_first() const { return m_first; }

    Type_m_second m_second;
}

这里只有A成员可以直接修改m_first 其他所有人都必须使用由get_m_first获得的const引用。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM