我有一个通过指针参数返回对象的函数。但是该对象有一个私有的默认构造函数,那么如何创建一个变量来传递地址?
<script src="~/sitecore modules/Web/Web Forms for Marketers/scripts/mvc/jquery-1.8.2.min.js"></script>
<script src="~/sitecore modules/Web/Web Forms for Marketers/scripts/mvc/jquery-ui-1.8.24.js"></script>
<script src="~/sitecore modules/Web/Web Forms for Marketers/scripts/mvc/jquery.validate.js"></script>
<script src="~/sitecore modules/Web/Web Forms for Marketers/scripts/mvc/jquery.validate.unobtrusive.js"></script>
<script src="~/sitecore modules/Web/Web Forms for Marketers/scripts/mvc/Fields/sc.fields-unobtrusive.js"></script>
<script src="~/sitecore modules/Web/Web Forms for Marketers/scripts/mvc/Fields/sc.fields-events-tracking.js"></script>
<script src="~/sitecore modules/Web/Web Forms for Marketers/scripts/mvc/Fields/sc.fields-date.js"></script>
<script src="~/sitecore modules/Web/Web Forms for Marketers/scripts/mvc/Fields/sc.fields-captcha.js"></script>
<script src="~/sitecore modules/Web/Web Forms for Marketers/scripts/mvc/Fields/sc.ajax-form.js"></script>
代码已简化,我无法真正更改class Foo {
Foo(/*some parameters*/);
private:
Foo();
};
void bar( Foo* foo ) {
*foo = Foo(/*some arguments*/);
}
Foo f; //doesn't compile because default constructor is private
bar( &f );
或Foo
答案 0 :(得分:2)
只需使用公共的非默认构造函数创建Foo
实例的第一个版本,该版本将在bar
中重新分配:
Foo f(/*some arguments*/);
bar(&f);
除非移动赋值运算符对旧值执行特殊操作,否则可能无法确定您传递的参数值。
是的,这似乎毫无意义,但Foo
的设计使得bar
使用起来非常不方便(或者反之亦然)。
所以没有办法说只是在内存中创建一个适合Foo的空间,我会在以后填写它?
不使用bar
。 bar
执行赋值,赋值要求左侧是现有对象,处于有效状态。
那么为什么在C ++中创建变量而不创建对象呢?
为什么它在C ++变量和对象中如此紧密相关?
因为这是指定C ++的方式。变量是对象的名称。它不是可能是对象或可能不是对象的东西的名称。这也是一个很好的决定。多亏了这个设计,您总是可以放心,变量命名的对象始终存在没有程序中的错误。 (参考变量是不同的,因为它们本身并不是一个对象)。
Foo
和bar
的问题不是语言的限制。问题是Foo
和/或bar
的设计不好。
答案 1 :(得分:1)
这不回答问题,因为它依赖于更改bar
,但回答此评论:
所以没有办法说只是在内存中创建一个适合Foo的空间,我会在以后填写它吗?
对于非平凡类型的对象(例如示例中的Foo
),唯一的方法是构造该地址的新对象,而不是分配给现有对象。您可以使用展示位置new-expression执行此操作:
void bar( Foo* foo ) {
new (foo) Foo(/*some arguments*/);
}
现在代替现有对象的地址,函数的参数需要是一块未初始化的内存,它与Foo
对象适当对齐,你可以使用{{1} } type:
aligned_storage
但是,因为您在该位置手动启动了std::aligned_storage<sizeof(Foo), alignof(Foo)>::type storage;
Foo* addr = reinterpret_cast<Foo*>(&storage);
bar( addr );
的生命周期,所以您还有责任通过在完成后显式调用析构函数来手动结束其生命周期:
Foo
这显然比依赖编译器自动构造和销毁对象更容易出错。
答案 2 :(得分:0)
我认为编写class Foo
代码的人不希望任何人使用默认的c&#tor来创建class Foo
的对象。相反,他/她想使用方法class Foo
;
bar()
的对象
所以试试这个:
class Foo {
Foo(/*some parameters*/);
private:
Foo();
};
void bar( Foo** foo ) {
//*foo = Foo(/*some arguments*/);
*foo = new Foo(/*some arguments*/);
}
Foo *f = NULL; //doesn't compile because default constructor is private
bar( &f );
注意:您需要创建一个指向class Foo i.e *f
的指针并传递该指针的地址。在方法bar()
内部,将创建class Foo
的对象,并将此对象的地址分配给指针f
。