为类成员分配内存

时间:2017-01-19 02:03:23

标签: c++ memory

我正在尝试为两种类似的类型提供统一的界面,一种处理double s,另一种处理float s。

class float_type {
  float_type() { /* does floaty stuff */ }
  float f();
};
class double_type {
  double_type() { /* does doubly stuff */ }
  double f();
};

我想编写一个分配一个或另一个的类,具体取决于程序需要做什么。 将float_type::f()转换为double的结果我完全没问题。事实上,它无论如何都会发生。 我试着像这样写:

class union_type {
  bool is_double;
  char mem[ sizeof(double_type) > sizeof(float_type)
          ? sizeof(double_type) : sizeof(float_type) ];
public:
  float_or_double_value_reader(bool is_double)
  : is_double(is_double)
  {
    if (is_double) new(mem) double_type();
    else new(mem) float_type();
  }

  ~float_or_double_value_reader() {
    if (is_double) delete static_cast<double_type*>(mem);
    else           delete static_cast< float_type*>(mem);
  }

  double f() {
    return (is_doubled
      ? static_cast<double_type*>(mem)->f()
      : static_cast< float_type*>(mem)->f()
    );
  }
};

但我得invalid static_cast from type 'char [128]' to type 'double_type'

我知道我可以添加一个成员指针来指向new返回的内容, 但那是多余的,因为我已经知道mem的位置, 所以我想避免这种情况。

如果我使用reinterpret_cast,我会在free(): invalid pointer:被销毁时在运行时获得union_type

这里适当的投射方法是什么?

3 个答案:

答案 0 :(得分:2)

reinterpret_cast应该是适当的投射方法。

但是,你不能简单地delete reinterpret_cast<double_type*>(mem),因为这不仅会破坏对象,还会释放内存,就好像它是用new分配的那样 - 它不是。

您可以使用reinterpret_cast<double_type*>(mem)->~double_type();销毁对象而不尝试释放内存。

当然,上述内容也适用于float_type

答案 1 :(得分:0)

更好的选择是提供铸造操作员。

我本可以为float类提供一个隐式double转换运算符来实现相同的接口

答案 2 :(得分:0)

您可以使用模板基类:

#include <iostream>

template < typename T >
class base_decimal
{
    public:
        base_decimal(T data) : _data(data) {}
        virtual ~base_decimal() {}
        T f() { return this->_data; }
        base_decimal& operator=(T val) { this->_data = val; }
        operator T() { return this->_data; }
        friend std::ostream& operator<<(std::ostream& os, const base_decimal& bd)
        {
            os << bd._data;
            return os;
        }
    private:
        T _data;
};

class float_type : public base_decimal<float>
{
    public:
        float_type(float f) : base_decimal<float>(f)
        {
            // do float stuff
        }
};

class double_type : public base_decimal<double>
{
    public:
        double_type(double d) : base_decimal<double>(d)
        {
            // do double stuff
        }
};

int main(int argc, char* argv[])
{
    float_type f = 1.2f;
    double_type d = 2.2;

    std::cout << "f = " << f << std::endl;
    std::cout << "d = " << d << std::endl;

    double rd = d;
    double rf = f;

    std::cout << "rf = " << rf << std::endl;
    std::cout << "rd = " << rd << std::endl;

    return 0;
}