C++ 访问类的私有数据

c++ access private data of the class

本文关键字:数据 访问 C++      更新时间:2023-10-16

我不知道我做错了什么?我有一个类,其中包含私有数据:

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

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

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

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

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

除了我的其他答案之外,这是我与代码的质量和维护性相关的建议。应使用容器(如 std::array)用于编译时数组,并使用成员初始值设定项列表来初始化数据成员。

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

int set[SIZE] = {0};

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

您还将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 样式数组。

以下是垃圾输出的说明:

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()循环中,您尝试从第一个索引(0)遍历ptrSIZE。您只给出了数组中 5 个位置的值,因此其他位置未初始化。这会导致程序出现未定义行为,并且是垃圾输出的原因。

应单独使用索引打印值。

但是,在您告诉我们您这样做的原因之前,我不能建议更好的替代方法。

数组set是构造函数的本地数组。因此,指向set的指针ptr,后来指向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;
}