[英]c++ inheritance question
I have a question about this: 我对此有一个疑问:
class A
{
int a;
int* pa;
public:
A(int i):a(i) , pa(new int(a))
{
cout<<"A ctor"<<a<<endl;
}
~A()
{
delete pa;
cout<<"dtor\n";
}
int * &get()
{
return pa;
}
};
class B : public A
{
int b;
public:
B (A obj): A(obj) , b(0)
{
cout<<"B ctor\n";
}
~B()
{
cout<<"B dtor\n";
}
};
int main()
{
int i = 23 ;
A* p = new B(i);
}
Can tell me why the last line in main
compiles? 能告诉我为什么main
编译的最后一行吗? I pass an int
into B
's constructor which expects an A
object instead. 我将int
传递给B
的构造函数,该构造函数期望使用A
对象。 I believe that the int
is translated to an A
in B
's constructor, but why? 我相信int
会转换为B
的A
的构造函数,但是为什么呢?
Thanks in advance. 提前致谢。
Avri. 阿夫里
Since you have not declared A
constructor as explicit
compiler is creating an anomymous instance of A
using i
and using it to initialize B
instance. 由于您尚未将A
构造函数声明为explicit
编译器,因此正在使用i
创建A
一个统一实例并使用其初始化B
实例。 If you don't want the compiler to do these implicit conversions declare your costructor as explicit
. 如果您不希望编译器执行这些隐式转换,则将您的构造explicit
声明为explicit
。 Then you will get a compiler error. 然后,您将得到一个编译器错误。
Because A
has a single parameter constructor which takes an int
and isn't marked explicit
you can implicitly convert an int
to an A
. 因为A
有一个带int
且未标记为explicit
参数构造函数,所以您可以将int
隐式转换为A
When you do new B(i)
, because the only viable constructor for B
takes an A
, an attempt is made to convert i
to an A
and construct the new B
from that. 当你做new B(i)
,因为是唯一可行的构造B
需要一个A
,试图转换i
到A
和构建新的B
从。 This conversion is done by creating a temporary A
using the constructor that takes an int
. 这种转换是通过使用带有int
的构造函数创建一个临时A
来完成的。
When the B
object is constructed, the base class A
is copy constructed from the temporary A
which means copying the member variables a
and pa
from the temporary A
. 当B
对象被构造,基类A
被复制从临时构造A
这意味着复制成员变量a
和pa
从临时A
。
Strictly, because the constructor takes an A
object by value, the temporary is, conceptually, copied again. 严格来说,由于构造函数按值接受A
对象,因此从概念上讲,临时副本将再次被复制。 The compiler may, however, eliminate the temporary by constructing the constructor parameter for B
directly from i
so the effect may well look like just a single copy. 但是,编译器可以通过直接从i
构造B
的构造函数参数来消除临时变量,因此效果很可能看起来像是单个副本。
This will cause a serious error because when the temporary A
is destroyed, delete pa
will cause the dynamically allocated int
to be destroyed but the base class A of the newly allocated B
object will still have a copy of this pointer which now no longer points at an invalid object. 这将导致严重的错误,因为当临时A
被销毁时, delete pa
将导致动态分配的int
被销毁,但是新分配的B
对象的基类A仍将具有此指针的副本,该指针现在不再指向无效的对象。 If the compiler doesn't eliminate one of the copies, a "double free" will happen immediately. 如果编译器没有消除其中一个副本,则将立即发生“双重释放”。
The key aspect of A
is that it has a user-defined destructor that performs a resource action (deallocation). A
的关键方面是它具有一个用户定义的析构函数,该析构函数执行资源操作(重新分配)。 This is a strong warning that A
needs a user-defined copy constructor and copy assignment operator because compiler generated version are likely not to work consistently with the design of A
. 强烈警告A
需要用户定义的拷贝构造函数和拷贝赋值运算符,因为编译器生成的版本可能与A
的设计不一致。
This is known as the "rule of three" which says that if you need a user-defined version of one of the destructor, copy constructor or copy assignment operator then you are likely to need user-defined versions of all of them. 这就是所谓的“三个规则”,它表示如果您需要析构函数,复制构造函数或复制赋值运算符之一的用户定义版本,则可能需要所有这些函数的用户定义版本。
Were you to attempt to free the dynamically allocated B
object in your example, it would likely cause a "double free" error. 如果您尝试释放示例中动态分配的B
对象,则可能会导致“双重释放”错误。 In addition, A
's destructor would need to be marked as virtual
for a delete through a pointer to A
to work correctly. 此外, A
的析构函数将需要被标记为virtual
的删除通过一个指向A
能够正常工作。
由于存在从int
到A
的转换,因此您的代码隐式转换为
A* p = new B(A(i));
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.