我主要是ac #programmer,但我正在研究的项目让我使用c ++.在C#中,我能够定义一个类的成员,其成员为null,直到初始化为止.像这样:
Class Foo{
private Bar _bar;
public Foo(int valueBarNeeds){
_bar = new Bar(valueBarNeeds);
}
}
Run Code Online (Sandbox Code Playgroud)
值为_barnull,并且在初始化之前禁止访问.此用例的基本原理是私有对象的构造函数依赖于在构造父类之前未知的某些值.
现在,在C++中,我尝试做同样的事情:
class Foo{
public:
Foo(int valueBarNeeds){
_bar = new Bar(valueBarNeeds);
}
private;
Bar _bar;
};
Run Code Online (Sandbox Code Playgroud)
编译器抛出一个错误,说没有bar的构造函数接受零参数.我的理解是,在C++中,new关键字意味着完全不同的东西.作为这种差异的一部分,人们可以通过声明没有new关键字来定义在方法结束时处置的对象,而无需手动删除.
SomeFunc(){
int valueBarNeeds = 100;
Bar _bar(valueBarNeeds);
_bar.SomeFunc();
}
Run Code Online (Sandbox Code Playgroud)
_bar 当方法堆栈超出范围时删除.
然后这就提出了我的问题.如果我在C#中用来创建单元化对象的语法实际上试图在C++中初始化对象...如何创建一个可以访问其他类方法的单元化类型,这些类方法是由父对象构造函数构建的?
问题是你所谓的“初始化”实际上并不是这样的。任何隐式或显式初始化的成员都在程序进入构造函数体之前初始化。
您的代码片段仅显示分配;在封装对象的构造函数的主体中执行此操作并不重要。这仍然只是任务。
Bar是一个类,因此您的成员_bar 将被隐式初始化,但实际上不能,因为该类没有不带参数的构造函数。为了提供参数,您必须自己显式初始化成员。
在 C++ 中,我们像这样初始化成员:
class Foo {
public:
Foo(int valueBarNeeds)
: _bar(valueBarNeeds)
{}
private:
Bar _bar;
};
Run Code Online (Sandbox Code Playgroud)
你也是对的,你new有点误会;与 Java 不同,它应该谨慎使用,因为对象基本上是通过简单地声明(并在必要时定义)它们来创建的。的使用为newfree store中的动态分配保留,并返回一个指针以供使用;这种用法应该很少见。您在最终代码片段中成功修复了此问题。
如何创建可由父对象构造函数构建的其余类方法可访问的单元化类型?
如果成员是一个类类型,它总是会被初始化。你不能拥有一个不存在的对象。你能得到的最接近的是封装一个指针而不是一个对象:
class Foo {
public:
Foo(int valueBarNeeds)
: _bar(nullptr)
{
// some time later...
_bar = new Bar(valueBarNeeds);
}
private:
Bar* _bar;
};
Run Code Online (Sandbox Code Playgroud)
但这在内存管理和诸如此类的方面打开了一堆蠕虫,如上所述,除非确实需要,否则应避免使用它。替代方案包括智能指针,但您仍应考虑尽可能坚持使用沼泽标准对象封装。您需要刻意将对象置于无效状态一段时间的情况应该很少见。