确保直接访问类成员
Secure direct access to class members
我想知道以下语法是否可以被"认可",或者良好的实践是否认为这是来自地狱。目标是增加一定程度的保护,迫使开发人员充分意识到自己在做什么。语法如下:
class MyClass
{
public:
template<bool RemoveProtection = false>
inline std::ofstream& writeStream()
{
static_assert(RemoveProtection, "You're doing it wrong");
return _writeStream;
}
inline const std::ofstream& writeStream() const
{
return _writeStream;
}
protected:
std::ofstream _writeStream;
};
用途是:
x.writeStream().good(); // <- OK
x.writeStream().put('c'); // <- NOT OK
x.writeStream<true>().put('c'); // <- OK
我发现这是一种方便的方式来告诉开发人员:"小心,你正在使用一个低级函数,你必须小心你正在做的事情"。这是一种"可接受"的方式,可以为班级成员提供一种"保护"吗?有没有其他编码方式?
看看米查尔的评论:
您正在使您的代码变得丑陋、难以维护并且不方便。。。究竟是什么?定义您的界面。这是你的类的接口。不要允许开发人员通过使用一些荒谬的模板标志技巧来绕过它。如果你在写代码,你必须知道你在做什么。必须显式键入
<true>
来表示您特别知道自己在做什么只是。。。头脑非常错误。开发人员有文档。他们不需要训练轮和人为的限制,他们需要清晰简洁的代码来完成任务微薄2012-10-06 02:41:53Z
当其他用户使用您提供给他人的类时,该类永远不会进入不可预测的状态。在这种情况下,不可预测状态是您在编写该类时从未考虑过的状态。因此,您应该永远不允许访问类的低级方法,或者记录可能的缺陷。
假设您正在编写一个记录器:
struct MyLogger{
MyLogger(std::string filename) : stream(filename.c_str()){}
template <typename T>
MyLogger& operator<<(const T& v){ stream << v << " "; return *this;}
private:
std::ofstream stream;
};
忽略没有复制构造函数以及缺少赋值操作数。还要忽略它是一个粗糙的记录器,它甚至不提供时间戳。然而,正如您所看到的,记录器的状态完全取决于记录器的方法,例如,如果文件已成功打开,则在记录器被销毁之前,它不会关闭。
现在说我们使用您的方法:
struct MyLogger{
MyLogger(std::string filename) : stream(filename.c_str()){}
template <typename T>
MyLogger& operator<<(const T& v){ stream << v << " "; return *this;}
template<bool RemoveProtection = false>
inline std::ofstream& writeStream()
{
static_assert(RemoveProtection, "You're doing it wrong");
return stream;
}
inline const std::ofstream& writeStream() const
{
return stream;
}
private:
std::ofstream stream;
};
现在有人使用以下代码
logger.writeStream<true>.close();
砰。你的记录器坏了。当然是用户的错,因为他们使用了<true>
,不是吗?但通常情况下,用户会复制示例代码,尤其是当他第一次使用库时。用户看到您的示例
logger.writeStream().good(); // <- OK
logger.writeStream().put('c'); // <- NOT OK
logger.writeStream<true>().put('c'); // <- OK
并且一开始完全忽略文档。然后他将使用第一个和最后一个版本。后来他发现最后一个版本每次都有效!<true>
是一件多么神奇的事情。然后他开始为发生的邪恶事情责怪你,所以你必须用一份包括警告的文件来保护自己免受公然的火焰的伤害:
/**
* brief Returns a reference to the internal write stream
*
* note You have to use the template parameter `<true>` in order to use it
*
* warning Please note that this will return a reference to the internal
* write stream. As such you shouldn't create any state in which
* the logger cannot work, such as closing the stream.
*/
template<bool RemoveProtection = false>
inline std::ofstream& writeStream()
{
static_assert(RemoveProtection, "You're doing it wrong");
return stream;
}
那么,我们得到了什么?我们还是得把警告放在某个地方。如果我们公开stream
,情况会简单得多:
struct MyLogger{
MyLogger(std::string filename) : stream(filename.c_str()){}
template <typename T>
MyLogger& operator<<(const T& v){ stream << v << " "; return *this;}
/**
* The internal write stream. Please look out that you don't create
* any state in which the logger cannot work, such as closing the stream.
*/
std::ofstream stream;
};
或粘贴到
/** >put warning here< */
inline std::ofstream & writeStream()
{
return stream;
}
呜呜。因此,要么不允许访问您的低级方法(如果应该允许特定的std::ofstream
方法使用,那么就为它们构建一个包装器),要么记录如果您过多地更改对象的内部,可能会出现的缺陷,但不要走中间路线,用static_assert
使其看起来不错。
- 这是关于成员访问规则的正确摘要吗
- 为什么我在空指针错误(链表)中获取成员访问权限
- 成员访问是否在空指针上定义C++?
- C++ IDE 不会推断/自动完成对模板类中的 std::array 下标表达式的成员访问
- 为什么类成员数据必须是静态的才能被模板化类的模板化结构成员访问
- 为什么c++允许成员函数定义中实例的私有成员访问
- C/C++ 包含点的宏参数(成员访问运算符)
- 访问说明符(私有/公共/受保护)如何在内部工作(限制成员访问)?
- 如何将超类的受保护成员访问到其派生类. 如果已在派生类中声明了具有相同名称的函数?
- 内部类私有成员访问和封闭的友好性
- 通过 C++ 中的另一个结构成员访问结构
- 具体化 PRVALUES 成员访问的 decltype 行为不正确
- 常量表达式中的静态成员访问
- XVALUE来自类成员访问表达式
- 未经授权的私有类成员访问会产生编译时错误而不是运行时错误?
- 在 c++ 中,为什么 -> 被称为二进制中缀指针成员访问运算符?
- 如何访问模板参数的成员?“成员访问不完整的类型”
- 不明确的可变参数类成员访问
- C 受保护的成员访问
- 将typeID转换为静态成员访问(C )的命名空间