创建类的实例后,我们可以显式调用构造函数吗?例如
class A{
A(int a)
{
}
}
A instance;
instance.A(2);
我们可以这样做吗?
创建类的实例后,我们可以显式调用构造函数吗?例如
class A{
A(int a)
{
}
}
A instance;
instance.A(2);
我们可以这样做吗?
您可以使用placement new,它允许
new (&instance) A(2);
但是,从您的示例中,您将在对象上调用构造函数两次,这是非常糟糕的做法。相反,我建议你这样做
A instance(2);
放置 new 通常仅在您需要预先分配内存(例如在自定义内存管理器中)并稍后构造对象时使用。
不。
为集合创建一个方法并从构造函数中调用它。以后也可以使用此方法。
class A{
A(int a) { Set(a); }
void Set(int a) { }
}
A instance;
instance.Set(2);
您可能还需要一个默认值或默认构造函数。
不
Calling instance.A() or A(1) is seens as casting 'function-style cast' : illegal as right side of '.' operator
通常,如果在构造函数中以及在构造对象之后需要函数/功能,则将其放置在 init() 方法中并在构造函数和其他地方使用。
例子:
class A{
A(int a)
{
init(a);
}
void init(int a) { }
}
A instance;
instance.init(2);
我很确定你不能那样做。这就是重点,构造函数是创建类的实例。
如果一个构造函数根本没有被调用,或者被调用了两次——它会产生什么后果?
当然,您可以做的是将一些构造函数逻辑提取到方法中,并在构造函数中和创建对象后调用该方法。
顺便说一句,这听起来像是一个设计缺陷。一旦构建了一个对象,就永远不需要重新构建它。这种变量名重用使代码更难理解。出于这个原因,通过额外的函数来提供类似构造函数的功能init
通常set
是错误的(但有时是不可避免的)。
正如 Michael 所说,placement new 可以在这里使用,但实际上是为了不同的用途。此外,在内存位置构造新对象之前,您必须显式销毁旧对象:
instance.~A();
此外,placement new
可能会对您的内存产生不利影响,因为重载可能会认为它传递的内存属于堆!结论:不要。做。这。
编辑为了证明调用析构函数确实是必要的(对于非 POD),请考虑以下示例代码:
#include <iostream>
struct A {
A(int a) { std::cerr << "cons " << a << std::endl; }
~A() { std::cerr << "dest" << std::endl; }
};
int main() {
A instance(2);
new (&instance) A(3);
}
正如预期的那样,程序产生以下输出:
cons 2
cons 3
dest
…这意味着第一个对象的析构函数没有被调用。任何A
可能已经获得的资源也是如此。
不,你不能那样做。调用构造函数的唯一方法是使用关键字“new”。
总结一下,指定显式构造函数的三种方法是通过
一个实例(2);// 做 A 实例 = 2; 曾经工作过吗?
A *实例 = 新 A(2); //我自己从不知道 & 和 * 的区别
新的 (&instance) A(2);
和那些味道。这个想法的目标是安排任何时候构造的对象都没有处于正确的初始化状态,并且构造函数旨在确保这一点。(这意味着方法不必检查某些 .init(...) 方法是否已成功调用。)
这让我觉得这是一种更实用的方法,特别是对于作为框架一部分并在库中重用的类。如果这是您感兴趣的内容,请努力让所有构造函数(包括任何默认构造函数)交付一个完整工作的实例。
异常情况:如果构造函数操作可能会失败,那么您可能在构造函数操作中没有某些东西,除非从构造函数抛出异常是合适的。有些人喜欢使用后续方法甚至暴露给初始化成员传播的“空白”实例。探索减轻这种情况的方法并拥有健壮的实例是很有趣的,这些实例没有需要在方法实现和使用中受到保护的不良状态。
PS:在某些复杂的情况下,将初始化实例(引用)作为“工厂”类上的函数或方法的结果传递可能很有用,这样中间的、设置不足的实例就不会出现在封装工厂类实例或函数之外。这给了我们,
+4。A *实例 = MakeAnA(2);
+5。A *instance = InterestingClass.A(2);