【问题标题】:How to create class member objects initialized during the constructor如何创建在构造函数期间初始化的类成员对象
【发布时间】:2013-11-10 22:48:36
【问题描述】:

我主要是一名 c# 程序员,但我正在从事的一个项目让我使用 c++。在 C# 中,我有能力定义一个类的成员,该成员在初始化之前为空。像这样:


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++ 中初始化对象...如何创建可由父对象构造函数构建的其余类方法可访问的单元化类型?

【问题讨论】:

    标签: c++ syntax


    【解决方案1】:

    问题是你所说的“初始化”实际上不是这样的。任何被初始化的成员,无论是隐式的还是显式的,都会在程序进入你的构造函数体之前被初始化。

    你的代码 sn-ps 只显示 assignment;在封装对象的构造函数主体中执行此操作并不重要。这仍然只是作业。

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

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

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

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

    如何创建可由其他类方法访问的单元化类型,该类型由父对象构造函数构建?

    如果成员是类类型,它将总是被初始化。你不能有一个不存在的对象。你能得到的最接近的是封装一个指针而不是一个对象:

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

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

    【讨论】:

    • 在您的最后一个示例中,您实际上不必使用 nullptr 初始化 _bar 吗?因为它是一个指针,所以没有调用构造函数,对吧? (或者用 nullptr 初始化只是一个好习惯?)
    • @null: 不,你没有必须这样做,但这是一个好主意,就像往常一样。
    【解决方案2】:

    你给你的类一个该类型的数据成员,并在构造函数的初始化列表中初始化它:

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

    一旦进入构造函数的主体,所有数据成员都已初始化。如果你没有在构造函数初始化列表中显式初始化它们,它们会得到default initialized,这意味着用户定义的类型会调用默认构造函数,而内置类型不会进行初始化。 p>

    【讨论】:

    • @LightnessRacesinOrbit 复制粘贴失败。
    猜你喜欢
    • 2018-12-21
    • 2021-12-26
    • 1970-01-01
    • 1970-01-01
    • 2016-05-03
    • 1970-01-01
    • 1970-01-01
    • 2023-03-14
    相关资源
    最近更新 更多