【发布时间】: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->transitionTo(std::unique_ptr<ConcreteStateB>());可以只是context->transitionTo(nullptr);。无论哪种情况,参数都会转换为std::unique_ptr<State>{nullptr}。 -
最好的办法是阅读相关的指导方针:isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Rc-private 简而言之,受保护的比公开的要好,但仍然为子类提供了破坏您可能有的任何期望的可能性变量。
-
你有没有想过关闭错误?
标签: c++ variables compiler-errors protected clang-tidy