提问人:CaG 提问时间:6/23/2023 最后编辑:CaG 更新时间:6/24/2023 访问量:91
如何使用派生类的属性和基类构造函数初始化派生类?
How can I initialize a derived class using its attributes and the base class constructor?
问:
从基类开始,我想创建一些派生类,这些派生类在许多数据成员的值上彼此不同。这些不同的属性在 BaseClass 构造函数中用于初始化其他数据成员。下面你可以找到一个简化的例子来说明我的意思;
class BaseClass {
public:
BaseClass(int a, double b, int c, std::string d) {
// Do stuff depending also on d
}
double f; // Inizialized in the BaseClass constructor
};
class DerivedClass1 : public BaseClass {
public:
DerivedClass1(int a, double b, int c) : BaseClass(a, b, c, d) {};
std::string d = "Hello";
};
class DerivedClass2 : public BaseClass {
public:
DerivedClass2(int a, double b, int c) : BaseClass(a, b, c, d) {};
std::string d = "Goodbye";
};
但是,我肯定做错了什么,因为我得到了.实现这一点的正确方法是什么?warning: field 'd' is uninitialized when used here [-Wuninitialized]
答:
在你给定的代码中,我认为你在这里错过了一点。在代码中:
class BaseClass {
public:
BaseClass(int a, double b, int c, std::string d) {
// Do stuff depending also on d
}
double f; // Inizialized in the BaseClass constructor
};
您已在构造函数中为基类设置了 4 个值。即 这意味着每当您调用基类的构造函数时,您都应该传入 4 个参数,而在此代码中: int a, double b, int c, std::string d
class DerivedClass1 : public BaseClass {
public:
DerivedClass1(int a, double b, int c) : BaseClass(a, b, c, d), d(d) {}
std::string d = "Hello";
};
class DerivedClass2 : public BaseClass {
public:
DerivedClass2(int a, double b, int c) : BaseClass(a, b, c, d), d(d) {}
std::string d = "Goodbye";
};
在这两堂课上,你一直在传递一些我不知道是什么的东西。
换言之,只需删除 .d(d)
d(d)
编辑:我发现你在这里也错过了一些东西:
class DerivedClass1 : public BaseClass {
public:
DerivedClass1(int a, double b, int c) : BaseClass(a, b, c, d), d(d) {}
std::string d = "Hello";
};
将代码块 : 置于构造函数的作用域之外。进行以下更改: std::string d="Hello";
class BaseClass {
public:
BaseClass(int a, double b, int c, std::string d) {
// Do stuff depending also on d
}
double f; // Inizialized in the BaseClass constructor
};
class DerivedClass1 : public BaseClass {
public:
std::string d="Anything you want to initialize d to is here";
DerivedClass1(int a, double b, int c) : BaseClass(a, b, c, d) {
//Constructor code
}
};
class DerivedClass2 : public BaseClass {
public:
std::string d="Same here as well";
DerivedClass2(int a, double b, int c) : BaseClass(a, b, c, d) {
//Constructor code
}
};
你就可以开始了。希望能有所帮助!!
评论
d(d)
d
您的问题是基本子对象是第一个初始化的东西。也就是说,这个:
class DerivedClass1 : public BaseClass {
public:
DerivedClass1(int a, double b, int c)
: BaseClass(a, b, c, d)
{};
std::string d = "Hello";
};
本质上等同于:
class DerivedClass1 : public BaseClass {
public:
DerivedClass1(int a, double b, int c)
: BaseClass(a, b, c, d),
d("Hello")
{};
std::string d;
};
d
在被 的构造函数初始化之前传递给 的构造函数。BaseClass
DerivedClass1
要解决此问题,您可以引入另一个包含额外成员的基类:
class DerivedBase {
public:
DerivedBase(std::string d) : d(d) {}
std::string d;
};
class DerivedClass1 : public DerivedBase, public BaseClass {
public:
DerivedClass1(int a, double b, int c)
: DerivedBase("Hello"),
BaseClass(a, b, c, d)
{}
};
由于基类是按照它们在类声明的 base-clause 中列出的顺序初始化的,因此将在 之前初始化,因此在传递给 的构造函数之前已经初始化。DerivedBase
BaseClass
d
BaseClass
问题在于,在派生类构造期间,基类构造函数在初始化派生类成员之前运行。这就是为什么编译器抱怨在调用基类构造函数时未初始化的原因 作为参数。d
d
如果我们保持你的声明不变,我认为你需要重复自己才能得到你想要的。
class DerivedClass1 : public BaseClass {
public:
DerivedClass1(int a, double b, int c) : BaseClass(a, b, c, "Hello") {};
std::string d = "Hello";
};
当然,重复自己并不是一件好事,但避免它意味着重构你的代码。 显然是一个概念(或者它的构造函数中不需要它)。如果将数据成员移动到 ,则初始化顺序问题将毫无意义。d
BaseClass
BaseClass
评论
d
DerivedClass1
DerivedClass1(int a, double b, int c) : BaseClass(a, b, c, d), d(d);
d(d)
d
BaseClass(a, b, c, "Goodbye")
d(d)
d
d
d = d
BaseClass
d
d
d(d)
d
BaseClass