C++ 继承问题

c++ inheritance question

提问人:Avri 提问时间:2/5/2011 最后编辑:CB BaileyAvri 更新时间:2/5/2011 访问量:168

问:

我有一个问题:

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

能告诉我为什么最后一行编译吗?我传递一个 into 的构造函数,它需要一个对象。我相信 the 被翻译成 in 的构造函数,但为什么呢?mainintBAintAB

提前致谢。

艾芙丽。

C++ 继承 explicit-constructor 三法则

评论


答:

5赞 Naveen 2/5/2011 #1

由于您尚未将构造函数声明为编译器正在创建一个使用并使用它来初始化实例的异常实例。如果您不希望编译器执行这些隐式转换,请将您的协构函数声明为 。然后,您将收到编译器错误。AexplicitAiBexplicit

1赞 Doc Brown 2/5/2011 #2

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

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

评论

0赞 Avri 2/5/2011
很棒的 tnx ,所以例如,如果我添加而不是 int 其他类型,例如 char*,该行将不会编译,因为 A 没有适当的 c'tor 来处理提到的类型。
2赞 CB Bailey 2/5/2011 #3

因为有一个参数构造函数,它接受一个 和 未标记,所以你可以隐式地将 转换为 .AintexplicitintA

当你这样做时,因为唯一可行的构造函数需要 ,所以会尝试转换为 an 并从中构造新的构造。此转换是通过使用采用 .new B(i)BAiABAint

构造对象时,基类是从临时变量(即复制成员变量)和临时变量复制构造的。BAAapaA

严格来说,由于构造函数按值获取对象,因此从概念上讲,临时对象会再次被复制。但是,编译器可以通过构造构造函数参数来消除临时参数 from 直接,因此效果可能看起来只是一个副本。ABi

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

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

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

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