Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何显式初始化没有默认构造函数的成员?_C++_Oop - Fatal编程技术网

C++ 如何显式初始化没有默认构造函数的成员?

C++ 如何显式初始化没有默认构造函数的成员?,c++,oop,C++,Oop,我已经绘制了一个非常简单的图表来遵循下面的描述,希望它能有所帮助: 我的问题是: 我需要classA中的classC对象。问题是classC需要构造函数中的两个参数,它们只能在classB中创建(在classB中调用init方法后),但现在,假设这个init方法调用得足够早。此外,我还有一个classD,它继承自classB最后,我还需要classD中的classA对象 如前所述,我需要在classA中创建classC对象。我不能直接在classA中创建它,因为我无法提供必要的参数(这些参数是

我已经绘制了一个非常简单的图表来遵循下面的描述,希望它能有所帮助:

我的问题是: 我需要classA中的classC对象。问题是classC需要构造函数中的两个参数,它们只能在classB中创建(在classB中调用init方法后),但现在,假设这个init方法调用得足够早。此外,我还有一个classD,它继承自classB最后,我还需要classD中的classA对象

如前所述,我需要在classA中创建classC对象。我不能直接在classA中创建它,因为我无法提供必要的参数(这些参数是在classB中创建的)。我的想法是在classB中创建classC对象(因为这是(我猜)用参数初始化对象的唯一方法。)然后,因为我在classD中需要一个classA的对象,并且classD继承自classB,我想我可以抓取classC的对象(创建于classB)在classD中(由于继承,应该是可能的,不是吗?),并将其作为构造函数的参数传递给classA。(我不希望classA继承自classD。)

这是一个好主意吗?在我缺乏经验的眼中,它看起来非常混乱,直到现在,我都无法让它工作(也许这是不可能的,或者可能我只是没有正确设置所有内容)。但我很乐意接受任何关于如何更优雅地解决此问题的建议。我感谢任何帮助

编辑 感谢所有的答案!我已经尽可能地简化了代码。我得到了一个错误,构造函数必须显式初始化classC的成员(请参见classA.cpp和classB.cpp注释)。但是初始化classC对象所需的参数是在classB中的
init
函数调用期间创建的。这里的问题是什么,即为什么会出现这些错误?我想,当我将一个类的对象作为另一个类的构造函数的参数传递时,我不需要再次实例化该类? 非常感谢您的帮助

A类

classA.h

#include <classC.h>

classA
{
    public:
        explicit classA(classC classC_object);
        void doSomething();
}

B类

classB.h

classB
{
    public:
        classB(int argc, char** argv);

        void init();

        classC classC_object;
}

classB.cpp

#include <classA.h>

classA::classA(classC classC_object) // Error: constructor for classC must explicitly initialize the member classC_object which does not have a default constructor
{
}

void classA::doSomething()
{
    classC_object.someMethod();
}
#include <classB.h>

classB::classB(int argc, char** argv) // Error: constructor for classB must explicitly initialize the member classC_object which does not have a default constructor
{
}

void classB::init()
{
    some_type_specificly_created_in_classB arg;
    classC classC_object(arg);
}
#include <classD.h>
#include <classA.h>

classD::classD(int argc, char** argv) : classB_object(argc, argv)
{
    classA_object = new classA(classB_object.classC_object);
}
D类

classD.h

#include <classB.h>
#include <classA.h>

classD
{
    public:
        classD(int argc, char** argv);

    private:
        classB classB_object;
        classA* classA_object;
}


您的代码与您的描述不匹配(例如,
D
不继承代码中的
B
)。还有一些编译器错误是由于语法不严谨引起的,例如在类定义中缺少关键字
class
。不过,我想这已经足够作为工作的起点了

总的来说,我怀疑您的设计存在应该解决的弱点,特别是在
classB::init()
方面。但是,这个问题没有(也可能不应该)足够的上下文来确定这一点。因此,我将按照对我有意义的顺序浏览您的类


让我们从
classC
开始,在我看来,它是这个设置的起点。您所拥有的看起来是合理的。该类有一个公共构造函数,它使用的参数只能从
classB
中获得,这几乎与您的描述相匹配。您的描述确实提到了两个参数,而不仅仅是一个,但不是一个HAT可能是一个微不足道的差异。只需标记构造函数<代码>显式< /代码> .<
我要看的下一个类是
classA
。您的描述说明了在classA中需要“一个classC的对象”,但这似乎在您的实现中被忽略了。另一方面,
classA::doSomething
引用了一个未定义的变量(
classC\u object
)。我的结论是,
classC\u对象
应该是
a
的成员,并且类型为
classC
。因此,我将继续并将该字段添加到您的类定义中

class classA
{
        classC classC_object;
    public:
        explicit classA(classC classC_object) : classC_object(std::move(classC_object)) {}
        void doSomething()
        {
            classC_object.someMethod();
        }
};
你的描述和你的代码都说
classA
不能构造
classC
对象。不过,我要指出的是,如果给定一个
某个特定类型的
对象,它就可以。当然,如果它破坏了封装,这将不是一个好的选择


现在我们来到
classB
,在这里我们面临一个难题。您声明了
classC
类型的成员,但该成员必须在
init()之前才能构造调用了
。不清楚如何在没有更好的上下文的情况下解决此问题。根据您的描述,我认为构造参数将存储在
classB
的对象中,而不是整个
classC
对象中。这是避免多次构造
classC
对象的优化吗?每个
classB
对象由于其他原因需要它的
classC
对象?如果两个答案都是“否”,您可能希望将
classC\U对象
替换为
classB arg
中特定创建的某个类型的对象,并添加基于
arg
构造并返回
classC
对象的成员函数

如果有理由让
init()
构造
classC
对象,这是可以做到的。但是,首先,去掉构造名为
classC\u object
的本地对象的donothing行–这不会影响同名成员,事实上,该声明会隐藏该成员(另请参见)。完成后,您可以将数据成员更改为某种类型的指针。此poi
class classA
{
        classC classC_object;
    public:
        explicit classA(classC classC_object) : classC_object(std::move(classC_object)) {}
        void doSomething()
        {
            classC_object.someMethod();
        }
};
#include <memory>

class classB
{
        std::unique_ptr<classC> classC_pointer;  // <-- pointer, and private.

    public:
        classB(int argc, char** argv) : classC_pointer()
        {
             // do something
             // ** Why is init() not part of this constructor? **
        }

        void init()
        {
            some_type_specificly_created_in_classB arg;
            std::make_unique<classC>(arg).swap(classC_pointer); // <-- construct classC object
        }

        const classC & getC()
        {
            if ( !classC_pointer ) // If the pointer is null
                init();
            return *classC_pointer;
        }
};
class classD : public classB
{
    public:
        classD(int argc, char** argv) : classB(argc, argv),
            classA_object{nullptr}
        {
            init();  // <-- You did say this would be called early enough!
            classA_object = new classA(getC());
        }

    private:
        classA* classA_object;
};
class classD : public classB
{
    public:
        classD(int argc, char** argv) : classB(argc, argv),
            classA_object(getC())
        {}

    private:
        classA classA_object; // <-- no longer a pointer
};