c ++访问该类的私有数据

时间:2013-10-23 19:20:53

标签: 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();
}

6 个答案:

答案 0 :(得分:6)

每个构造函数都声明一个名为set的新数组,它会隐藏类成员。

答案 1 :(得分:1)

您正在设置ptr来设置在构造函数中定义的设置,而不是设置为类变量的设置。在构造函数中更改以下内容:

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

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

答案 2 :(得分:1)

除了my other answer之外,我的建议还与代码的质量和可维护性有关。您应该使用std::array等容器作为编译时数组,并使用成员初始化列表来初始化数据成员。

您误解了以下代码行将set的内容设置为0。

int set[SIZE] = {0};

当它覆盖set类中的私有数据成员IntegerSet并在构造函数中创建局部变量时。这就是为什么你应该使用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;
    }
};

答案 3 :(得分: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风格的数组。

答案 4 :(得分:0)

数组set是构造函数的本地。因此,当控件退出构造函数时,指向ptr的指针set,稍后指向NULL,因为数组set不存在。

使用作为实例变量的数组set,以便在构造函数和set方法中具有相同的print实例。

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;
}

答案 5 :(得分:0)

以下是垃圾输出的说明:

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

在main方法中,您使用了参数1,50,10,22和98.因此上例中的第一行等同于:

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

这并没有错。问题是它下面发生的事情。在for()循环中,您尝试将ptr从其第一个索引(0)迭代到SIZE。您只给出了数组中5个位置的值,因此其他值未初始化。这会导致程序出现未定义的行为,并且是导致garabage输出的原因。

您应该分别使用索引打印值。

但是直到你能告诉我们你这样做的原因是什么,我不能建议一个更好的替代方法。