C++ 初始化列表成员仍在调用默认构造函数?
C++ initializer list members still calling default constructor?
我在初始化我正在处理的 class 的 shared_ptr
成员时遇到问题。
我有两个 classes,A
和 B
:
class A {
int _x;
int _y;
public:
A(int, int);
};
A::A(int x, int y) {
_x = x;
_y = y;
}
class B : public A {
std::shared_ptr<A> _a;
public:
B(std::shared_ptr<A>);
};
B::B(std::shared_ptr<A> a) : _a(a) {}
int main() {
std::shared_ptr<A> a = std::make_shared<A>(1, 2);
B b(a);
return 0;
}
我只想 class B
将 std::shared_ptr
保存到 class A
的实例。
但是,我在 B
的构造函数中收到错误 no matching function for call to A::A()
。
我很困惑,因为我认为初始化列表的目的是避免隐式调用成员变量的默认构造函数,但它似乎仍在尝试调用 A
的默认构造函数。
感谢任何解释,谢谢。
编辑:经过更多的折腾,如果 B
没有继承自 A
,它似乎是正确的。仍然不确定为什么从 A
继承会导致从 B
的构造函数调用 A
的默认构造函数。
由于 B
源自 A
,因此每个 B
都是一个 A
。也就是说,要构造一个B
,还必须构造一个A
。但是,您没有告诉 B
的构造函数如何构造一个 A
,因此使用默认构造函数。
如果你想让B
派生自A
并且只持有一个shared_ptr
到A
,那么A
不能做任何你不做的事情'想要 B
做。这里,A
有 _x
和 _y
.
不清楚你真正想要什么,但也许你想要一些其他基础 class,A
和 B
都从中派生出来,只有 A
B
应该有。
C++ 中继承的 classic 示例类似于 Instrument
是基础 class,具有成员 Play
和派生 classes像 Trumpet
和 Clarinet
拥有使某些特定乐器成为小号的东西。只有 Trumpet
s 和 Clarinet
s 的共同点应该在 Instrument
.
中
当您调用 B b(a);
时,您使用构造函数 B::B(std::shared_ptr<A> a)
.
构造了一个 B
对象
问题出在您对此构造函数的定义中。 B
继承自 A
,这意味着 B
不仅仅是一个 B
,而是一个真正的 A
和 B
堆叠在上面彼此。 A
是基数class,所以在底部。因此,当您尝试构造一个 B
对象时,代码必须首先在 bottom/base 处构造 A
对象,以形成 B
对象存在的基础。这意味着您实际上必须告诉代码如何构造 A
对象。
因为您为 A
定义了一个带有两个 int
变量的构造函数,所以编译器不会为 A
生成默认构造函数。因此,您必须明确写出 A
应该如何在 B
中构建。构造 A
对象可以在 B
对象的构造函数的初始化列表中完成:
B::B(std::shared_ptr<A> a) : A(0,0), _a(a) {}
我在初始化我正在处理的 class 的 shared_ptr
成员时遇到问题。
我有两个 classes,A
和 B
:
class A {
int _x;
int _y;
public:
A(int, int);
};
A::A(int x, int y) {
_x = x;
_y = y;
}
class B : public A {
std::shared_ptr<A> _a;
public:
B(std::shared_ptr<A>);
};
B::B(std::shared_ptr<A> a) : _a(a) {}
int main() {
std::shared_ptr<A> a = std::make_shared<A>(1, 2);
B b(a);
return 0;
}
我只想 class B
将 std::shared_ptr
保存到 class A
的实例。
但是,我在 B
的构造函数中收到错误 no matching function for call to A::A()
。
我很困惑,因为我认为初始化列表的目的是避免隐式调用成员变量的默认构造函数,但它似乎仍在尝试调用 A
的默认构造函数。
感谢任何解释,谢谢。
编辑:经过更多的折腾,如果 B
没有继承自 A
,它似乎是正确的。仍然不确定为什么从 A
继承会导致从 B
的构造函数调用 A
的默认构造函数。
由于 B
源自 A
,因此每个 B
都是一个 A
。也就是说,要构造一个B
,还必须构造一个A
。但是,您没有告诉 B
的构造函数如何构造一个 A
,因此使用默认构造函数。
如果你想让B
派生自A
并且只持有一个shared_ptr
到A
,那么A
不能做任何你不做的事情'想要 B
做。这里,A
有 _x
和 _y
.
不清楚你真正想要什么,但也许你想要一些其他基础 class,A
和 B
都从中派生出来,只有 A
B
应该有。
C++ 中继承的 classic 示例类似于 Instrument
是基础 class,具有成员 Play
和派生 classes像 Trumpet
和 Clarinet
拥有使某些特定乐器成为小号的东西。只有 Trumpet
s 和 Clarinet
s 的共同点应该在 Instrument
.
当您调用 B b(a);
时,您使用构造函数 B::B(std::shared_ptr<A> a)
.
B
对象
问题出在您对此构造函数的定义中。 B
继承自 A
,这意味着 B
不仅仅是一个 B
,而是一个真正的 A
和 B
堆叠在上面彼此。 A
是基数class,所以在底部。因此,当您尝试构造一个 B
对象时,代码必须首先在 bottom/base 处构造 A
对象,以形成 B
对象存在的基础。这意味着您实际上必须告诉代码如何构造 A
对象。
因为您为 A
定义了一个带有两个 int
变量的构造函数,所以编译器不会为 A
生成默认构造函数。因此,您必须明确写出 A
应该如何在 B
中构建。构造 A
对象可以在 B
对象的构造函数的初始化列表中完成:
B::B(std::shared_ptr<A> a) : A(0,0), _a(a) {}