是否有任何已建立的模式来检查 C++ 中的类不变量?
理想情况下,将在每个公共成员函数的开始和结束时自动检查不变量。据我所知,带有类的 C 语言提供了特殊before
的after
成员函数,但不幸的是,当时契约式设计并不是很流行,除了 Bjarne 之外没有人使用该功能,因此他将其删除。
当然,check_invariants()
在每个公共成员函数的开头和结尾手动插入调用既繁琐又容易出错。由于 RAII 是处理异常的首选武器,因此我提出了以下方案,将不变性检查器定义为第一个局部变量,并且该不变性检查器在构造和销毁时检查不变量:
template <typename T>
class invariants_checker
{
const T* p;
public:
invariants_checker(const T* p) : p(p)
{
p->check_invariants();
}
~invariants_checker()
{
p->check_invariants();
}
};
void Foo::bar()
{
// class invariants checked by construction of _
invariants_checker<Foo> _(this);
// ... mutate the object
// class invariants checked by destruction of _
}
问题#0:我想没有办法声明一个未命名的局部变量?:)
我们仍然必须check_invariants()
在构造函数的末尾和析构函数Foo
的开头手动调用。Foo
但是,许多构造函数体和析构函数体是空的。在那种情况下,我们可以使用 aninvariants_checker
作为最后一个成员吗?
#include <string>
#include <stdexcept>
class Foo
{
std::string str;
std::string::size_type cached_length;
invariants_checker<Foo> _;
public:
Foo(const std::string& str)
: str(str), cached_length(str.length()), _(this) {}
void check_invariants() const
{
if (str.length() != cached_length)
throw std::logic_error("wrong cached length");
}
// ...
};
问题 #1:即使对象仍在构造中,传递this
给invariants_checker
立即通过该指针调用的构造函数是否有效?check_invariants
Foo
问题 #2:您认为这种方法还有其他问题吗?你能改进它吗?
问题 3:这种方法是新的还是众所周知的?有没有更好的解决方案?