从另一个构造函数的主体中调用构造函数

时间:2018-08-22 23:33:17

标签: c++

将对象初始化的一部分委派给另一个构造函数的典型方法(也是唯一一种广泛使用的方法)是使用初始化列表来调用它,如下所示:

class Window
{
  Window(int a);
  Window(int a, void *b);
  Window(string a);

  Window(double a, double b) : Window((int) (a + b))
  {
  }
};

但是有时候有必要做一些准备工作或分支构造函数调用。

这应该怎么做?

class Window
{
  Window(int a);
  Window(int a, void *b);
  Window(string a);

  Window(double a, double b)
  {
    if (a * b == 0.0)
    {
      Window("ZERO");
    }
    else if (a * b > 100.0)
    {
      Window((int) (a + b), x);
    }
    else
    {
      Window((int) (a + b));
    }
  }
};

我从未见过这样的事情;这只是我对它的外观的猜测(似乎可行)。

从构造函数主体(而不是从初始化列表中)调用其他构造函数是否有副作用或未定义行为?

@Edit:下面包含了我有问题的代码。基本上,我有一个对象,它是一些数据的容器,并将其存储在std::map<CString, ValueContainer>中。我使用了一个复制构造函数和一个重载的赋值运算符。当我使用[]运算符将实例添加到地图时,插入效果很好,但是当我使用insert_or_assign方法时,插入效果就不好了,因为它使用了复制构造函数(它使用的是这里的问题)。这是该类的简化。

class ValueContainer
{
  ValueContainer(const VOID *p_data, ULONG p_size)
  {
    if (p_data != NULL)
    {
      if (p_size > 0)
      {
        if (p_size <= sizeof(shortData))
        {
          memcpy(shortData, p_data, p_size);
        }
        else
        {
          longData = new BYTE[p_size];

          memcpy(longData, p_data, p_size);
        }
      }

      hasValue = TRUE;
      size = p_size;
    }
    else
    {
      hasValue = FALSE;
      size = 0;
    }
  }

  ValueContainer(const ValueContainer &p_value)
  {
    if (p_value.HasValue())
    {
      if (p_value.size <= sizeof(shortData))
      {
        ValueContainer(p_value.shortData, p_value.size);
      }
      else
      {
        ValueContainer(p_value.longData, p_value.size);
      }
    }
    else
    {
      ValueContainer();
    }
  }

  ValueContainer(VOID) : ValueContainer(NULL, 0)
  {
  }

  ValueContainer &operator =(const ValueContainer &p_value);
  {
    if (p_value.hasValue)
    {
      if (p_value.size <= sizeof(shortData))
      {
        if (longData != NULL)
        {
          free(longData);

          longData = NULL;
        }

        memcpy(shortData, p_value.shortData, p_value.size);
      }
      else
      {
        if (p_value.size > size)
        {
          longData = (BYTE *) realloc(longData, p_value.size);
        }

        memcpy(longData, p_value.longData, p_value.size);
      }

      hasValue = TRUE;
      size = p_value.size;
    }
    else
    {
      if (longData != NULL)
      {
        free(longData);

        longData = NULL;
      }

      hasValue = FALSE;
      size = 0;
    }

    return *this;
  }

private:
  BYTE  shortData[16];
  BYTE *longData = NULL;
  BOOL  hasValue;
  ULONG size;
}

2 个答案:

答案 0 :(得分:2)

对于您的第一个示例,这可能是完成操作的方式:

First call:
a(1)  -> 1 < 20 so return b(3)     ^ return 39 --> final result: 39
b(3)  -> return c(3) + 1           │ return 38 + 1 = 39
c(3)  -> return a(6)               │ return 38
a(6)  -> 6 < 20 so return b(8)     │ return 38
b(8)  -> return c(8) + 1           │ return 37 + 1 = 38
c(8)  -> return a(16)              │ return 37
a(16) -> 16 < 20 so return b(18)   │ return 37
b(18) -> return c(18) + 1          │ return 36 + 1 = 37
c(18) -> return a(36)              │ return 36
a(36) -> 36 > 20 so return 36 ─────┘

答案 1 :(得分:2)

我认为这个问题的简短答案是“简化代码”。但是,如果这不是一种选择,那么我认为下一个最佳选择是工厂方法:

class Window
{
private:
    Window(int a);
    Window(int a, void *b);
    Window(string a);

public:
    static Window Create(double a, double b)
    {
        if (a * b == 0.0)
        {
            return Window("ZERO");
        }
        else if (a * b > 100.0)
        {
            return Window((int) (a + b), x);
        }
        else
        {
            return Window((int) (a + b));
        }
    }
};