简体   繁体   English

C ++继承问题

[英]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会转换为BA的构造函数,但是为什么呢?

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 ,试图转换iA和构建新的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这意味着复制成员变量apa从临时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能够正常工作。

由于存在从intA的转换,因此您的代码隐式转换为

 A* p = new B(A(i));

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM