如何在类静态成员中引用静态变量?

时间:2017-05-23 11:23:53

标签: c++

我想将C模块封装到C ++类中。

在C实现中,有一个函数将指针指向静态const

const BIGNUM *BN_value_one(void)
{
    static const BN_ULONG data_one = 1L;
    static const BIGNUM const_one =
        { (BN_ULONG *)&data_one, 1, 1, 0, BN_FLG_STATIC_DATA };

    return (&const_one);
}

我想让它成为一个类中的静态方法,析构函数执行一些释放操作

class BigNumber
{

    struct deleter
    {
        void operator() (BIGNUM *it)
        {
            BN_free(it); // The freeing operation provided by origin C library
        }
    };


    using BN_ptr = std::unique_ptr<BIGNUM, deleter>;

    /* The OpenSSL BIGNUM pointer */
    BN_ptr bn;

public:
    BigNumber() : bn(BN_new(), ::BN_free) {}
    BigNumber(BigNumber &&other) : bn(std::move(other.bn)) {}
    BigNumber(const BigNumber &other) : bn(BN_new(), ::BN_free)
    {
        ::BN_copy(bn.get(), other.bn.get());
    }
    BigNumber(BIGNUM *src) : bn(src, ::BN_free) {}

    static const BigNumber one()
    {
        static const BigNumber o(const_cast<BIGNUM *>(::BN_value_one()));
        return o;
    }
}

由于one()方法将unique_ptr返回到BN_value_one中的静态变量,因此在销毁返回值时会发生分段错误。

有没有办法避免这种破坏,或者更好的封装?

1 个答案:

答案 0 :(得分:2)

当您使用openssl库时,您不必使用BN_free(),因为您的代码从未使用BIGNUM分配BN_new()。有关详细说明,请参阅此manpage

所以你不需要unique_ptr也不需要删除。

编辑#1:

我看到您的班级也可以保留已分配的BIGNUM值。因此,有两种方法可以区分已分配和未分配的BIGNUM值。

  1. 您的BigNumber类可以提供两个不同的构造函数。您可以将分配状态保存在标志中,并在unique_ptr
  2. 的删除例程中进行检查
  3. 您可以使用多态来提供从一个接口类继承的两个不同的类。一个类实现一个什么都不做的删除器,另一个实现一个实际调用BN_free()的删除器。
  4. 编辑#2:

    现在您的代码更完整了。您可以编写一个附加构造函数,该构造函数接受指向使用自己的虚拟自由函数的const BIGNUM的指针。如果使用此构造函数,则必须避免使用const_cast

    BigNumber(const BIGNUM *src) : bn(src, ::BN_dummy_free) {}
    

    虚拟自由应该是这样的:

    void BN_dummy_free(BIGNUM *a) {}
    

    这应该适用于您的代码,并且不会以分段错误结束。所以你可以选择已分配和未分配的BIGNUM。

    此外,您应该注意复制构造函数,因为它始终使用BN_free()。您应该复制使用过的删除函数,该函数可能是BN_dummy_free()函数。