2013-10-23 49 views
1

我無法弄清楚我做錯了什麼?我有一個班級,其中有私人數據:C++訪問該類的私人數據

static const int SIZE = 101; 
int *ptr; 
int set [SIZE]; 

而我有2個構造函數。一個是將數組設置爲0的默認構造函數。 另一個需要5個參數並將數組中的5個值設置爲1. 我需要打印此數組。當我在構造函數中一切正常時,當我在構造函數內執行cout < <時,結果是正確的。但是當我嘗試使用功能打印。結果是垃圾。我做錯了什麼?

IntegerSet::IntegerSet() //default constructor 
{ 
    int set[SIZE] = {0}; 
    ptr = set; 
    cout << "Default Constructor: " << endl; 
    for (int i =0; i<SIZE ;i++) 
    { 
     cout << set[i] << " "; 
    } 
    cout << endl; 
} 


IntegerSet::IntegerSet(int a, int b, int c, int d, int e) 
{ 
    int set[SIZE] = {0}; 
    ptr = set; 

    ptr[a] = ptr[b] = ptr[c] = ptr[d] = ptr[e] = 1; 

    cout << "Constructor with 5 parametrs: " << endl; 
    for (int i =0; i<SIZE ;i++) 
    { 
     cout << ptr[i] << " "; 
    } 
    cout << endl; 
} 

void IntegerSet::print() const 
{ 
    bool flag = false; 
    cout << "I am in print: " << endl; 

    for (int i=0;i<SIZE;i++) 
    { 
     if (ptr[i]==1) 
     { 
      cout << i << " "; 
      flag = true; 
     } 
    } 
    if (flag == false) 
     cout << "-----"; 
    cout << endl; 
} 


void main() 
{ 
    IntegerSet s1; 
    IntegerSet s2(1,50,10,22,98); 

    s2.print(); 
} 
+2

它的垃圾因爲set在堆棧中,所以指針(ptr)在退出構造函數時無效。 – drescherjm

+0

我該怎麼辦? – user2001019

+0

改爲使用矢量,不要在構造函數中重新聲明它。 – drescherjm

回答

6

你的構造函數中的每一個聲明瞭一個名爲set新陣列陰影類的成員。

+0

如果我改變這個int set [SIZE] = {0}; ptr = set;至此\t設置[SIZE] = 0; ptr = set;結果是正確的,但我有錯誤:堆棧變量已損壞。 – user2001019

+0

@ user2001019您需要將'set()'放在構造函數初始化列表中。你不能分配給普通數組。 – juanchopanza

+0

由於'set'只有'SIZE'成員,'set [SIZE]'超出了界限。 –

1

您正在設置ptr以在您的構造函數中定義,而不是作爲類變量的集合。改變你的構造如下:

int set[SIZE] = {0}; 
ptr = set; 

set[SIZE-1] = {0}; 
ptr = set; 
+0

應該是'set [SIZE-1] = {0};'然後 – helb

+0

是的,編輯答案。 – AsG

+0

謝謝,明白了 – user2001019

0

你把int set[SIZE] = {0};在構造,以及,這堆(這「影子」的私有成員變量,它是定義了一個局部set也稱爲set)。

如果你正在嘗試做set[SIZE] = 0(將set的最後一個元素設置爲0),那麼你有第二個錯誤:你正在訪問set越界(C和C++中的數組是0索引的。大小爲5的數組具有有效索引(0,1,2,3和4))。你應該做set[SIZE-1] = 0。或者更好的是,使用std::vectorstd::array(C++ 11)而不是C風格的數組。

0

數組set是構造函數的本地對象。因此指針ptr指向set,稍後指向NULL,因爲當控件離開構造函數時數組set不存在。

使用數組set這是實例變量,因此您在構造函數中以及在print方法中都具有相同的set實例。

IntegerSet::IntegerSet()           //default constructor 
{ 
    set[SIZE-1] = {0}; 
    ptr = set; 
    cout << "Default Constructor: " << endl; 
    for (int i =0; i<SIZE ;i++) 
    { 
     cout << set[i] << " "; 
    } 
    cout << endl; 
} 


IntegerSet::IntegerSet(int a, int b, int c, int d, int e) 
{ 
    set[SIZE-1] = {0}; 
    ptr = set; 

    ptr[a] = ptr[b] = ptr[c] = ptr[d] = ptr[e] = 1; 

    cout << "Constructor with 5 parametrs: " << endl; 
    for (int i =0; i<SIZE ;i++) 
    { 
     cout << ptr[i] << " "; 
    } 
    cout << endl; 
} 
+0

謝謝!!!!!!!!!!! – user2001019

0

這裏是您的垃圾輸出的解釋:

ptr[a] = ptr[b] = ptr[c] = ptr[d] = ptr[e] = 1; 
// ... 
for (int i = 0; i < SIZE; i++) 
{ 
    cout << ptr[i] << " "; 
} 

在你的主要方法時,使用的參數1,50,10,22,和98。因此,第一線在上述示例相當於:

ptr[1] = ptr[50] = ptr[10] = ptr[22] = ptr[98] = 1; 

並且沒有什麼問題。問題是它下面發生的事情。在您的for()循環中,您試圖將ptr從其第一個索引(0)迭代到SIZE。你只給出了數組中5個位置的值,所以其他的都是未初始化的。這會導致程序出現未定義的行爲,並且是garabage輸出的原因。

您應該分別使用索引打印值。

但是,除非你能告訴我們你做這件事的原因是什麼,否則我不能建議一種更好的替代方法。

+0

,因爲我之前將數組整數設置爲0,那麼我將5個元素更改爲1 – user2001019

+0

'ptr = set'不會將'set'的副本分配給'ptr'。事情是,'set' *從數組中衰減*到一個指針,所以'set'的零初始化不適用於'ptr'。 – 0x499602D2

1

除了my other answer,這裏是我的建議與您的代碼的質量和可維護性有關。您應該使用容器,如編譯時數組的std::array以及用於數據成員初始化的成員初始化程序列表。

你是那個下面的代碼線設置的set內容爲0。

int set[SIZE] = {0}; 

當而是掩蓋了私有數據成員setIntegerSet類,並創建在一個局部變量的誤解下構造函數。這就是爲什麼你應該爲這些專長使用STL容器的原因之一。例如:

#include <array> // for std::array 

class IntegerSet 
{ 
private: 
    std::array<int, 101> set; 
public: 
    IntegerSet() 
     : set() // zero-initializes each element 
    { 
     for (auto val : set) 
      std::cout << val " "; 
     std::cout << std::endl; 
    } 

    IntegerSet(int a, int b, int c, int d, int e) 
     : set() 
    { 
     set[a] = set[b] = set[c] = set[d] = set[e] = 1; 

     for (auto val : set) 
      std::cout << val " "; 
     std::cout << std::endl; 
    } 
};