将对象初始化的一部分委派给另一个构造函数的典型方法(也是唯一一种广泛使用的方法)是使用初始化列表来调用它,如下所示:
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;
}
答案 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));
}
}
};