代码之家  ›  专栏  ›  技术社区  ›  ivanTheTerrible

指向类内对象的指针,C++ Nebe问题

  •  1
  • ivanTheTerrible  · 技术社区  · 17 年前

    为什么在C++中,对于对象A、B

    //interface, case #1
    class A {
    
    B bb;
    }
    
    A::A()
    { //constructor
    bb = B();
    }
    
    
    //interface, case #2
    class A {
    
    B *bb;
    }
    
    A::A()
    { //constructor
    bb = new B();
    }
    

    为什么案例2起作用而不是1起作用??

    编辑:我现在知道了。但是对于案例1,如果一个实例被释放,它的bb也将 自动地 释放?案例2您必须显式地调用bb=null,对吗?

    8 回复  |  直到 17 年前
        1
  •  -1
  •   Mykola Golubyev    17 年前

    问题 至于我 是如何制作的

    A::A()
    { //constructor
    bb = new B();
    }
    

    但没有新的。我想问题中的代码不是真正的代码。为什么“新”有效,但简单的任务却不行。

    我的答案 正在跟进。如果我理解错误的问题或答案本身是错误的-请告诉我。

    变化

    A::A()
    { //constructor
    bb = B();
    }
    

    A::A():
        bb()
    {
       // some logic
    }
    

    为了与“new”保持一致,最好实现如下

    A::A():
        bb( new B() )
    {
        // some logic
    }
    

    在这两种情况下,当“某些逻辑”开始执行时,可以确保对象bb已初始化或将引发异常。

    为了使您的案例可编译,b应该已经实现了assign操作符。

    您的编辑: 你对案例1的猜测是正确的。在情况2中,您必须在类析构函数中调用delete bb。

    请留言 关于-1'原因 . 我真的很困惑。

        2
  •  4
  •   Pete Kirkham    17 年前

    两者都有语法错误,因此“不起作用”不是特定于一个或另一个的。您还没有声明 A::A 构造器,所以当您试图定义它时会得到一个语义错误。

    如果B的完整声明在A级声明之前可用,那么它将编译:

    class B {};
    
    //interface
    class A {
        A();
    
        B bb;
    };
    
    A::A()
    { //constructor
        bb = B();
    }
    

    bb=B() 行,b b已经被构造,因为它是a的一个成员。然后您要构造另一个b,然后将b的值复制到b b。这有点浪费。如果要将参数传递给bb的构造函数,请使用初始化器。

    另一方面,如果你不想把B的定义放在A的定义之前,并且只对它有一个正向引用,那么编译器就无法计算出B对象有多大。它需要知道a b有多大才能决定a中b b的空间大小,所以没有b它就无法编译a。

    在第二种情况下,使用指向b的指针。指针的大小与它们指向的大小相同。这样,编译器就可以计算出a有多大,并且在实际使用b之前只需要b的完整声明,例如,通过在 new B() 表达式。

        3
  •  2
  •   SurDin    17 年前

    在C++中,如果声明一个对象,则不需要初始化它。在声明时调用构造函数。

        4
  •  2
  •   Steven Oxley    17 年前

    因为在编译时,创建B对象所需的内存量是未知的。因此,有必要使用指向对象的指针,以便在调用new时动态分配内存。

        5
  •  1
  •   Suma    17 年前

    显示的代码太不完整。除非你给出B的定义,恐怕没人能回答。我猜想B类是不可复制的(例如,private operator=)。对于一个可复制的B类,您给出的示例应该是有效的。

        6
  •  1
  •   Reed Copsey    17 年前

    看起来您的“B”类隐藏了运算符。否则,您编写的应该编译。

    但是,这是不必要的。这应该有效:

    A::A() : bb()
    { //constructor
    }
    

    但是,由于您正在调用默认的构造函数,因此不需要显式地声明它。这很容易做到:

    A::A() // bb is automatically constructed, since it's a member variable and not a pointer.
    { 
    }
    

        7
  •  1
  •   Community Mohan Dere    9 年前

    如果B类的定义(而不是声明)出现在A类声明之前,那么您的案例1应该编译得很好。

    AS Oxley 指出,原因是C++需要知道B对象需要多少内存,如果没有B的定义,它就不能这么做。

    但是,如果使用指针(如案例2),则所需的内存量是已知的,因为所有指针占用相同的内存量(32位或64位,具体取决于系统)。

    因此,对于案例2,您只需要在定义a之前声明b。(注意:声明,而不是定义!当然,有了这个定义也不会有什么伤害,但不一定需要。

    只是为了确保我不会混淆任何人,(嘿,也许我没有C++术语了)

    声明:声明类或函数的存在,但不说明它是什么。

    例如

    class A; //forward declaration
    
    class C
    {
       A * a;
       // .....
    };
    

    定义:实际定义类或函数。尽管对于一个类,它不一定完全定义它,但它定义了它的所有成员。

    class A
    {
       int a;
       int b;
       void some_method(); //not defined here, only declared, but it's ok
    };
    
        8
  •  0
  •   Jesus Fernandez    17 年前

    我认为案例A必须起作用,因为如果没有定义任何人,编译器会提供一个复制构造函数。

    推荐文章