2016-10-25 54 views
-4

我在想以下创建类的对象的方式有什么区别。头文件是:创建类的对象的方法

class NumberRange { 
public: 
    NumberRange(int a, int b); 
    virtual ~NumberRange(); 
    void Print(int a, int b); 
private: 
    int *range_; 
    int size; 
}; 

.cc文件是:

#include <iostream> 
#include "numberrange.h" 
using namespace std; 

NumberRange::NumberRange(int a, int b) { 
    if (a > b) { 
     cout << "a must be equal or less than b" << endl; 
    } 
} 

NumberRange::~NumberRange() { 

} 

void NumberRange::Print(int a, int b) { 
    this->size = b - a + 1; 
    this->range_[0] = a; 
    for (int i = 0; i < this->size; i++) { 
     this->range_[i] = a + i; 
     cout << this->range_[i] << endl; 
    } 
} 

int main() { 
    NumberRange * numberrange = new NumberRange(5, 9); 
    numberrange->Print(5, 9); 
} 

当我使用指针创建一个对象,并编译该程序。我得到一个错误说:[1] 20346 segmentation fault ./numberrange

,但如果我改变的主要功能为:

int main() { 
    NumberRange numberrange(5,9); 
    numberrange.Print(5,9); 
} 

这将是工作。所以我不知道什么时候应该用指针来创建一个对象。谢谢!

+0

该对象的其中一个字段是'int * range_'。你永远不会在构造函数中初始化/分配它,所以在Print函数中使用它将是未定义的行为。有时它会起作用,有时不起作用。首先解决问题,然后重试。 –

+3

你错过了分配'range_',那很简单。所以你调用未定义的行为。未定义的行为是......好的......未定义的。 –

+0

如果第二个工作,那只是因为你运气好。你访问'range_'对象而不给它任何存储,这是未定义的行为。 – Chad

回答

1

你的程序至少有三个问题。

第一个最明显的问题是int * range_是一个指向整数的指针,但并不指向任何特别的东西。它只是包含一个随机存储器地址。 要改变这种情况,可以为它分配一个int数组,例如你使用new创建的int数组。 :

range_ = new int [b - a]; 

第二,不太明显的问题是,你通过a和b两次你的对象,首先在构造函数和后面的打印方法(最好不要利用方法,顺便说一句)。 ++在C++中为您提供的一件事是面向对象。对象有状态。如果您希望NumberRange类的对象存储从3到7的数字,请使用构造函数将它们存储为属性。无需在Print方法中再次传递边界,它可以从属性中读取它们。

第三个更不明显的问题是,在你的例子中,根本不需要存储数字,因为你只是想打印它们。

问题二和三相连接。或许你想用数字做更多的事情,而不仅仅是打印它们。所以构造函数要么存储a和b,要么分配一个数组并存储从a到b的数字。后者的效率较低,但可能稍后想要存储不相邻整数的序列。

3

你有一个指针range_在你的类中,你没有在构造函数中初始化。然后在Print方法中使用它,在两种情况下都会导致UB。事实上,该程序不会在第二种情况下崩溃并不意味着您的程序是正确的。