c++继承问题

发布于 2024-10-16 06:37:46 字数 741 浏览 3 评论 0原文

我对此有一个问题:

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);
}

可以告诉我为什么 main 中的最后一行可以编译吗?我将一个 int 传递到 B 的构造函数中,该构造函数需要一个 A 对象。我相信 intB 的构造函数中被转换为 A,但为什么呢?

提前致谢。

阿夫里。

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? I pass an int into B's constructor which expects an A object instead. I believe that the int is translated to an A in B's constructor, but why?

Thanks in advance.

Avri.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

木緿 2024-10-23 06:37:46

由于您尚未将 A 构造函数声明为 explicit,编译器正在使用 i 创建 A 的匿名实例并使用它初始化 B 实例。如果您不希望编译器执行这些隐式转换,请将您的构造函数声明为显式。然后你会得到一个编译器错误。

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. If you don't want the compiler to do these implicit conversions declare your costructor as explicit. Then you will get a compiler error.

萌逼全场 2024-10-23 06:37:46

由于 A 有一个采用 int 且未标记为 explicit 的单参数构造函数,因此您可以隐式转换 int > 到 A

当您执行 new B(i) 时,由于 B 唯一可行的构造函数采用 A,因此会尝试转换 iA 并从中构造新的 B。此转换是通过使用采用 int 的构造函数创建临时 A 来完成的。

当构造 B 对象时,基类 A 是从临时 A 复制构造的,这意味着复制成员变量 a< /code> 和来自临时 Apa

严格来说,因为构造函数按值获取 A 对象,所以从概念上讲,临时对象被再次复制。然而,编译器可以通过直接从 i 构造 B 的构造函数参数来消除临时参数,因此效果很可能看起来只是一个副本。

这会导致严重错误,因为当临时A被销毁时,delete pa会导致动态分配的int被销毁,但基类新分配的 B 对象的 A 仍将具有此指针的副本,该指针现在不再指向无效对象。如果编译器没有消除其中一个副本,则会立即发生“双重释放”。

A 的关键方面是它有一个用户定义的析构函数来执行资源操作(释放)。这是一个强烈警告,表明 A 需要用户定义的复制构造函数和复制赋值运算符,因为编译器生成的版本可能与 A 的设计不一致。

这被称为“三规则”,它表示如果您需要析构函数、复制构造函数或复制赋值运算符之一的用户定义版本,那么您可能需要所有这些的用户定义版本。

如果您尝试释放示例中动态分配的 B 对象,则可能会导致“双重释放”错误。此外,A 的析构函数需要标记为virtual,以便通过指向 A 的指针进行删除才能正常工作。

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.

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. This conversion is done by creating a temporary A using the constructor that takes an int.

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.

Strictly, because the constructor takes an A object by value, the temporary is, conceptually, copied again. 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.

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. 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). 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.

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. In addition, A's destructor would need to be marked as virtual for a delete through a pointer to A to work correctly.

捶死心动 2024-10-23 06:37:46

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

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

Since there is a conversion from int to A, implicitly your code is translated into

 A* p = new B(A(i));
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文