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