gpt4 book ai didi

c++ - 在 C++ 中检查不变量

转载 作者:IT老高 更新时间:2023-10-28 22:28:31 26 4
gpt4 key购买 nike

在 C++ 中是否存在用于检查类不变量的既定模式?

理想情况下,将在每个公共(public)成员函数的开头和结尾自动检查不变量。据我所知,带有类的 C 提供了特殊的 beforeafter 成员函数,但不幸的是,当时契约式设计并不是很流行,除了 Bjarne 之外没有人使用该功能,因此他将其删除。

当然,在每个公共(public)成员函数的开头和结尾手动插入 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:我想没有办法声明一个未命名的局部变量? :)

我们仍然需要在 Foo 构造函数的末尾和 Foo 析构函数的开头手动调用 check_invariants()。但是,许多构造函数体和析构函数体是空的。在这种情况下,我们可以使用 invariants_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:这种方法是新的还是众所周知的?有没有更好的解决方案?

最佳答案

答案#0:你可以有未命名的局部变量,但是你放弃了对对象生命周期的控制——对象的全部意义在于你有一个好主意超出范围。你可以使用

void Foo::bar()
{
invariants_checker<Foo>(this); // goes out of scope at the semicolon
new invariants_checker<Foo>(this); // the constructed object is never destructed
// ...
}

但两者都不是你想要的。

答案 #1: 不,我认为它无效。 this 引用的对象仅在构造函数完成时才完全构造(并因此开始存在)。你在这里玩的是一场危险的游戏。

答案 #2 & #3: 这种方法并不新鲜,一个简单的谷歌查询例如“检查不变量 C++ 模板”将在该主题上产生大量热门话题。特别是,如果您不介意重载 -> 运算符,则可以进一步改进此解决方案,如下所示:

template <typename T>
class invariants_checker {
public:
class ProxyObject {
public:
ProxyObject(T* x) : m(x) { m->check_invariants(); }
~ProxyObject() { m->check_invariants(); }
T* operator->() { return m; }
const T* operator->() const { return m; }
private:
T* m;
};

invariants_checker(T* x) : m(x) { }

ProxyObject operator->() { return m; }
const ProxyObject operator->() const { return m; }

private:
T* m;
};

这个想法是,在成员函数调用期间,您创建一个匿名代理对象,该对象在其构造函数和析构函数中执行检查。您可以像这样使用上面的模板:

void f() {
Foo f;
invariants_checker<Foo> g( &f );
g->bar(); // this constructs and destructs the ProxyObject, which does the checking
}

关于c++ - 在 C++ 中检查不变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4736044/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com