具有受保护可见性的变量的风险是啥

Posted

技术标签:

【中文标题】具有受保护可见性的变量的风险是啥【英文标题】:What are the risks of variables with protected visibility具有受保护可见性的变量的风险是什么 【发布时间】:2021-09-12 18:35:29 【问题描述】:

我正在尝试实现example 中解释的状态模式。我已经编写了类似如下的代码。

class State 
public:
    virtual void enter() ;
    virtual void update() = 0;
    virtual void exit() ;

    virtual void setContext(Context* cxt) 
        this->context = cxt;
    
protected:
    Context* context;
;

class Context 
public:
    void do_something();
    void do_something_else();

    void transitionTo(std::unique_ptr<State> next_state) 
        if (state != nullptr) 
            state->exit();
        
        state = std::move(next_state);
        state->setContext(this);
        state->enter();
    

private:
    std::unique_ptr<State> state;
;

class ConcreteStateA : public State 
public:
    void update() override 
        try 
           context->do_something();
         catch 
           context->transitionTo(std::unique_ptr<ConcreteStateB>());
        
       
;

class ConcreteStateB 
 // ...
;

但是,当我尝试使用 clang-tidy 编译它时,我收到以下警告

error: member variable 'context' has protected visibility [cppcoreguidelines-non-private-member-variables-in-classes,-warnings-as-errors]

我有以下 2 个问题:

    为变量提供受保护的可见性有哪些风险? 是否有人对如何以干净的方式解决此错误有任何建议? (我一直在努力创建一个受保护的 getter 方法,但如果我想根据正确的上下文采取行动,我将不得不返回一个引用或指针,这与此具有相同的效果,但只需要额外的代码)。

【问题讨论】:

我认为预期的解决方案是使其成为 private 并提供 protected 吸气剂。突出的风险可能是派生类型可能分配给context,而State 似乎不允许这样做。我不明白你为什么需要返回对指针的引用,关键是要防止有人让 context 指向不同的对象。 context 是指向非const 的指针,因此您仍然可以对指向的对象进行操作。编辑:上下文有一个 public 设置器,所以我猜这个推理并不真正适用。但是,这可能仍然是诊断的原因。 在我看来context-&gt;transitionTo(std::unique_ptr&lt;ConcreteStateB&gt;()); 可以只是context-&gt;transitionTo(nullptr);。无论哪种情况,参数都会转换为std::unique_ptr&lt;State&gt;nullptr 最好的办法是阅读相关的指导方针:isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Rc-private 简而言之,受保护的比公开的要好,但仍然为子类提供了破坏您可能有的任何期望的可能性变量。 你有没有想过关闭错误? 【参考方案1】:

    你说的不对

    我将不得不返回一个引用或指针,其效果与此相同,但只需要额外的代码

    因为通过使其受保护来暴露指针允许派生类型 操纵指针本身,而不仅仅是底层数据。

    来自文档 misc-non-private-member-variables-in-classes 检查哪个 cppcoreguidelines-non-private-member-variables-in-classes 是一个 别名:

    数据成员应声明为私有并通过成员函数访问,而不是暴露给派生类或 类消费者。

【讨论】:

以上是关于具有受保护可见性的变量的风险是啥的主要内容,如果未能解决你的问题,请参考以下文章

受保护的静态成员变量

为啥以下用于切换两个容器的可见性的代码不起作用,正确的做法是啥?

在不“推”其他元素的情况下切换图像可见性的最佳方法是啥?

WPF 触发器绑定:将枚举值绑定到可见性的最佳方法是啥?

Java--继承

为啥 Java 允许增加子类中受保护方法的可见性?