如何创建在构造函数期间初始化的类成员对象

时间:2013-11-10 22:48:37

标签: c++ syntax

我主要是一名c#程序员,但我正在研究的项目让我使用c ++。在C#中,我能够定义一个类的成员,其成员为null,直到初始化为止。像这样:


Class Foo{
    private Bar _bar;
    public Foo(int valueBarNeeds){
        _bar = new Bar(valueBarNeeds);
    }
}

_bar的值为null,在初始化之前禁止访问。此用例的基本原理是私有对象的构造函数依赖于在构造父类之前未知的某些值。

现在,在C ++中,我尝试做同样的事情:


class Foo{
public:
    Foo(int valueBarNeeds){
        _bar = new Bar(valueBarNeeds);
    }
private;
    Bar _bar;
};

编译器抛出一个错误,指出没有带零参数的bar的构造函数。我的理解是,在C ++中,new关键字意味着完全不同的东西。作为这种差异的一部分,可以通过在没有new关键字的情况下声明来定义放置在方法末尾的对象,而无需手动删除。


SomeFunc(){
    int valueBarNeeds = 100;
    Bar _bar(valueBarNeeds);
    _bar.SomeFunc();
}
当方法堆栈超出范围时,将删除

_bar

然后设置我的问题。如果我在C#中用来创建单元化对象的语法实际上试图在C ++中初始化对象...如何创建一个可以访问其他类方法的单元化类型,它由父对象构造函数构建?

2 个答案:

答案 0 :(得分:4)

问题在于你所谓的“初始化”实际上并非如此。任何初始化,隐式或显式的成员都会在程序进入构造函数体之前进行初始化。

您的代码段仅显示分配;你在封装对象的构造函数体中这样做并不重要。它仍然只是作业。

Bar是一个类,因此您的成员_bar 隐式初始化,但它实际上不能是因为该类没有构造函数不带参数。为了提供参数,您必须自己明确初始化该成员。

在C ++中,我们初始化这样的成员:

class Foo {
public:
    Foo(int valueBarNeeds)
     : _bar(valueBarNeeds)
    {}
private:
    Bar _bar;
};

你也是对的,你有点误解new;与Java不同,它应该谨慎使用,因为对象基本上是通过简单地声明(并在必要时定义)它们来创建的。 new的使用保留用于免费存储中的动态分配,并返回一个指针供使用;这种用法应该很少见。您已在最终的代码段中成功修复此问题。

  

如何创建一个可以访问由父对象构造函数构建的其余类方法的单元化类型?

如果该成员属于类类型,则始终将被初始化。您不能拥有不存在的对象。最接近的是封装指针而不是对象:

class Foo {
public:
    Foo(int valueBarNeeds)
     : _bar(nullptr)
    {
       // some time later...
       _bar = new Bar(valueBarNeeds);
    }
private:
    Bar* _bar;
};

但是这会在内存管理等方面打开一堆蠕虫,如上所述,除非你确实需要,否则你应该避免它。替代方案包括智能指针,但您仍应考虑尽可能坚持使用沼泽标准对象封装。您需要在一段时间内故意将对象置于无效状态。

答案 1 :(得分:3)

您为类提供该类型的数据成员,并在构造函数的初始化列表中初始化它:

class Foo
{
 public:
     Foo(int valueBarNeeds) :_bar(valueBarNeeds) {}
 private:
     Bar _bar;
};

进入构造函数体后,所有数据成员都已初始化。如果你没有在构造函数初始化列表中显式初始化它们,它们会得到默认初始化,这意味着为用户定义的类型调用默认构造函数,并且不对内置类型执行初始化。