C ++对象实例化和范围

时间:2011-09-23 11:47:42

标签: c++

我来自(最近)来自C#,我习惯于实例化这样的对象:

Phone myPhone = new Phone();

简单地写

Phone myPhone;

基本上为一个类创建了一个持有者,但它还没有被初始化。

现在我正在用C ++编写一个小类,我遇到了问题。这是伪代码:

Phone myPhone;

void Initialise()
{
    myPhone = new Phone();
}

void DoStuff()
{
    myPhone.RingaDingDong();
{

实际上这有点误导,因为上面的代码是我想要的,因为我希望能够将我的所有初始化代码放到一个整洁的地方。我的问题是在C ++中初始化内部的行是不必要的,因为在此之前,已经创建了一个新实例并由第一行初始化。另一方面,如果我将第一行放在Initialise()中,我就无法在DoStuff中访问它。它超出了范围,(更不用说在C ++中使用'new'或不使用'之间的区别)。如何为类变量创建一个简单的持有者,以便我可以在一个地方初始化它,并在另一个地方访问它?或者我得到了一些根本错误的东西?

提前致谢!

5 个答案:

答案 0 :(得分:2)

您可以在指针上使用new运算符:

Phone *myPhone;

void Initialise()
{
    myPhone = new Phone();
}

void DoStuff()
{
    myPhone->RingaDingDong();
}

在访问*时,仅有两项更改是myPhone声明中添加的->.而非RinaDingDong()。您还必须释放它,因为new正在分配内存:

void destroy()
{
    delete myPhone;
}

请注意,如果您这样做,myPhone将成为指向Phone而非实际Phone的指针。

答案 1 :(得分:2)

如果您的Phone构造函数没有参数,那么您的生活非常简单 - 您无需在Initialize方法中新建手机。在创建对象并为您管理生命周期时,将为您创建它。

如果需要获取参数,并且它没有Initialize()方法或某些set方法,那么您可能需要使用指针(有时可以为null)并使Initialize()调用new并传递这些参数。您的其他代码需要在使用之前检查指针是否为空。您还需要管理生命周期(通过编写大3)或使用智能指针,如C ++ 11中的shared_ptr。这不应该是你的首选。

答案 2 :(得分:0)

我认为你需要在指针上刷一点。 你可以用指针做什么。

  

我的问题是在C ++中初始化内部的行是不必要的,因为在此之前,已经创建了一个新实例并由第一行初始化。

这是不正确的。您提供的评论仅适用于构造函数。从您的puesdo代码,函数initialize是一个全局函数,不是类的成员函数。

  

另一方面,如果我将第一行放在Initialise()中,我就无法在DoStuff中访问它。它超出了范围,(更不用说在C ++中使用'new'或不使用'之间的区别)。

请参阅有关指针的任何书籍,您可以使用全局指针并使用new进行初始化。这可以在doStuff中使用

答案 3 :(得分:0)

如果你来自C#,你知道你有两种类型的对象:class和struct。

通过引用复制,分配和传递类。因此,他们使用的是参考语义。该类也在堆中分配(使用new)。

struct正在实现一个值复制语义。 struct在堆栈上分配(int,double和其他内置类型是struct)。你不能处理struct polymorphicaly。

在C ++中,你没有这个区别。类和结构本质上是相同的(默认访问级别的一部分)。确定复制语义不是类的声明,而是实例对类的声明。

如果创建指针,则行为与c#中的类非常相似。如果创建对象,则语义将类似于c#中的结构。

C ++也有参考,你应该阅读指针和引用之间的区别。

答案 4 :(得分:0)

凯特格雷戈里的答案是正确的,但我想详细说明一下。 C ++中更强大的一个想法是堆栈分配的对象由其包含的范围所拥有。例如,如果你想写一个包含手机的课程,你只需写下:

class Secretary { 
    Phone myPhone;
};

现在每次创建一个秘书时,都会使用默认构造函数自动初始化Phone对象。更重要的是,每当一个Secret对象被销毁时,它所包含的Phone对象也会被销毁。如果要为Phone使用不同的构造函数,可以在Secretary的构造函数中使用初始化列表:

class Secretary {
private: // members
    Phone myPhone;
    Phone myCellPhone;

public: // methods
    Secretary() : myPhone("phone constructor", 12, " args") {}
};

在这种情况下,myPhone使用其3参数构造函数初始化,并且myCellPhone像往常一样使用其默认构造函数进行初始化。