指向类中对象的指针,C++;新手问题 为什么在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(); }

指向类中对象的指针,C++;新手问题 为什么在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(); },c++,class,pointers,oop,C++,Class,Pointers,Oop,为什么案例2有效,但案例1无效 编辑:我现在知道了。但对于案例1,如果A的一个实例被释放,它的bb是否也会自动被释放?案例2你必须在C++中显式调用BB= NULL?< P>,如果你声明一个对象,你不需要初始化它。在声明时调用构造函数 > C++中,如果声明一个对象,则不需要初始化它。在声明时调用构造函数 因为在编译时,创建B对象所需的内存量是未知的。因此,有必要使用指向对象的指针,以便动态分配内存(当您调用new时)。因为在编译时,创建B对象所需的内存量未知。因此,有必要使用指向对象的指针,以

为什么案例2有效,但案例1无效


编辑:我现在知道了。但对于案例1,如果A的一个实例被释放,它的bb是否也会自动被释放?案例2你必须在C++中显式调用BB= NULL?

< P>,如果你声明一个对象,你不需要初始化它。在声明时调用构造函数

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

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

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

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

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

对于我来说,问题是如何

A::A()
{ //constructor
bb = new B();
}
但是没有新的。我想问题中的代码不是真正的代码。这就是为什么“新”有效,而简单的作业无效

我的答案如下。如果我理解问题的方式有误,或者答案本身有误,请让我知道

改变

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

为了与“新”保持一致,最好像这样实现

A::A():
    bb( new B() )
{
    // some logic
}
在这两种情况下,当“某些逻辑”将开始执行时,您可以确保对象bb已初始化或将引发异常

为了使您的案例可编译,B应实现assign运算符

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


请留言说明“-1”原因。我真的很困惑。

对我来说,问题是如何做

A::A()
{ //constructor
bb = new B();
}
但是没有新的。我想问题中的代码不是真正的代码。这就是为什么“新”有效,而简单的作业无效

我的答案如下。如果我理解问题的方式有误,或者答案本身有误,请让我知道

改变

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

为了与“新”保持一致,最好像这样实现

A::A():
    bb( new B() )
{
    // some logic
}
在这两种情况下,当“某些逻辑”将开始执行时,您可以确保对象bb已初始化或将引发异常

为了使您的案例可编译,B应实现assign运算符

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

请留言说明“-1”原因。我真的很困惑。

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

然而,这是没有必要的。这应该起作用:


A::A():bb()
{//构造函数
}

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


A::A()//bb是自动构造的,因为它是一个成员变量而不是指针。
{ 
}

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

然而,这是没有必要的。这应该起作用:


A::A():bb()
{//构造函数
}

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


A::A()//bb是自动构造的,因为它是一个成员变量而不是指针。
{ 
}

我认为案例A必须工作,因为如果没有定义任何人,编译器将提供一个副本构造函数。

我认为案例A必须工作,因为如果没有定义任何人,编译器将提供一个副本构造函数。

两者都有语法错误,因此“不工作”不是特定于其中一个。您还没有声明
A::A
构造函数,因此在尝试定义它时会出现语义错误

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

class B {};

//interface
class A {
    A();

    B bb;
};

A::A()
{ //constructor
    bb = B();
}
bb=B()
行中,bb已经被构造,因为它是a的成员。然后,您正在构造另一个B,然后将该B的值复制到bb。那有点浪费。如果要将参数传递给bb的构造函数,请使用初始化器

另一方面,如果您不想将B的定义放在A的定义之前,并且只对其进行正向引用,编译器就无法计算出B对象的大小。它需要知道AB有多大才能确定a中允许bb的空间有多大。因此,如果没有B,它将无法编译a


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

两者都有语法错误,因此“不起作用”并不特定于其中一个。您还没有声明
A::A
构造函数,因此在尝试定义它时会出现语义错误

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

class B {};

//interface
class A {
    A();

    B bb;
};

A::A()
{ //constructor
    bb = B();
}
<
class A
{
   int a;
   int b;
   void some_method(); //not defined here, only declared, but it's ok
};