在c++中,如何使用私有变量是一系列对象?

发布于 2025-02-05 05:52:50 字数 1664 浏览 1 评论 0原文

我正在尝试学习C ++,并弄清楚如何访问作为对象数组的私人成员变量。我的目标是试图打印出对象数组中的数据。假设我的标题看起来像这样。

using namespace std;

const unsigned MAX_RESULTS = 10;

class StudentRecords{
public:
  StudentRecords();

  //bunch of other getters and setters here

  Result GetResults() const; //my lame attempt at trying to access the obj-array private var

private:
  Result results[MAX_RESULTS]; // array of Result of MAX_RESULTS number of elements
  //+other private variables
};

ostream& operator <<( ostream& os, const StudentRecords& R);

在上面,应该有一个称为结果的私有结果对象数组,该对象具有Max_Results的大小,应该在这里10。现在,使用我的超载运算符&&lt;这个想法是将结果内容打印到“文件”以说话。由于它是一个数组,所以我想使用for循环打印出数组中的所有结果。

Result StudentRecords::GetResults() const
{
    return results[MAX_RESULTS];
}

ostream & operator <<( ostream & os, const StudentRecords& R )
{
  for(unsigned i = 0; i < SomeNumber; i++)
  {
      os << R.GetResults()[i] << '\n'; //this won't work of course see error
  }
  return os;
}

会有一个错误说明:

error: no match for 'operator[]' (operand types are 'Result' and 'unsigned int')|

我已经超载了&lt;&lt;我的结果类中的运算符为了打印该类中的值。问题是我不知道如何通过结果阵列迭代。从我搜索的内容来看,我了解您可以在此处使用某种指针函数: c ++:数组的设置和获取器

当我尝试以这样的方式编写功能时:

Result* GetResults() const;

我会发现一个错误说明:

error: cannot convert 'const Result' to 'Result*' in return|

抛弃 *允许代码编译,但可以预见,我从我的我那里得到了一堆垃圾值大批。因此,假设我的班级有一系列对象,而这些对象有自己的变量,那么我如何从我的对象数组中打印出值?感谢您的帮助。

I'm trying to learn C++ and figuring out how to access a private member variable that is an array of objects. My objective is trying to print out the data that's in the array of objects. Suppose that my header looks like this.

using namespace std;

const unsigned MAX_RESULTS = 10;

class StudentRecords{
public:
  StudentRecords();

  //bunch of other getters and setters here

  Result GetResults() const; //my lame attempt at trying to access the obj-array private var

private:
  Result results[MAX_RESULTS]; // array of Result of MAX_RESULTS number of elements
  //+other private variables
};

ostream& operator <<( ostream& os, const StudentRecords& R);

In the above, there is supposed to be a private array of Result objects called results, which has a size of MAX_RESULTS, which is supposed to be 10 here. Now, using my overloaded operator << the idea is to print the contents of Result to 'file' so as to speak. Since it's an array, I want to print out all the results in the array using a for loop.

Result StudentRecords::GetResults() const
{
    return results[MAX_RESULTS];
}

ostream & operator <<( ostream & os, const StudentRecords& R )
{
  for(unsigned i = 0; i < SomeNumber; i++)
  {
      os << R.GetResults()[i] << '\n'; //this won't work of course see error
  }
  return os;
}

There will be an error stating:

error: no match for 'operator[]' (operand types are 'Result' and 'unsigned int')|

I already overloaded the << operator in my Result class in order to print out the values in that class. The problem is that I don't know how to iterate through the results array. From what I've googled I understand that you can use some kind of pointer function for example here: C++: Setters and Getters for Arrays

When I try to write the function like this:

Result* GetResults() const;

I will get an error stating:

error: cannot convert 'const Result' to 'Result*' in return|

Leaving out the * allows the code to compile, but predictably I get a bunch of garbage values from my array. So assuming that my class has an array of objects, and those objects have their own variables, how do I print out the values from my array of objects? I appreciate the help.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

池予 2025-02-12 05:52:50
Result StudentRecords::GetResults() const
{
    return results[MAX_RESULTS];
}

这是一个常见的新手误解。因为您声明将数组作为结果[max_results]您认为结果[max_results]以某种方式意味着整个数组。但这不是,当您使用时, array []用于访问数组的各个元素。当然,索引max_results上没有元素,这已经过去了数组的末尾。

最重要的是,声明的语法和表达式语法不是相同的。

您可以执行这样的操作,

const Result* StudentRecords::GetResults() const
{
    return results;
}

这是返回数组的指针,而不是数组本身(实际上在C ++中不可能做到这一点)。但这应该足够近。

Result StudentRecords::GetResults() const
{
    return results[MAX_RESULTS];
}

This is a common newbie misunderstanding. Because you declared the array as results[MAX_RESULTS] you think that results[MAX_RESULTS] somehow means the whole array. But it doesn't, when you are using an array [] is used to access individual elements of the array. And of course there is no element at index MAX_RESULTS, that's past the end of the array.

Bottom line is that the syntax for declarations and the syntax for expressions is not the same.

You could do something like this

const Result* StudentRecords::GetResults() const
{
    return results;
}

This returns a pointer to the array, not the array itself (which is actually impossible to do in C++). But that should be close enough for now.

爱人如己 2025-02-12 05:52:50

一种方法是使类的输出功能部分使其可以直接访问Resulte数组。尽管运营商&lt;&lt;从字面上看不到您的课程的一部分,但您可以通过将其声明为朋友来使其成为逻辑上的一部分。

class StudentRecords {
    friend ostream& operator <<( ost& os, const StudentRecords& R);
    // Rest of the class definition
};

ostream & operator <<(ostream & os, const StudentRecords& R)
{
    for(unsigned i = 0; i < MAX_RESULTS; i++) {
        os << R.results[i] << '\n';
    }
    return os;
}

另外,您可以通过定义打印数组并具有操作员&lt;&lt;调用该成员的成员函数来避免友谊。

class StudentRecords {
  public:
    void print_to(std::ostream& os) const
    {
        for(unsigned i = 0; i < MAX_RESULTS; i++) {
            os << results[i] << '\n';
        }
    }
    // Rest of the class definition
};

ostream & operator <<(ostream & os, const StudentRecords& R)
{
    R.print_to(os);
    return os;
}

请注意,这种方法是针对班级以外其他任何其他内容都需要访问结果数组的情况。如果您需要外部访问该数组,则不妨修复您的Getter(如其他答案中),并使用该公共访问权限进行打印。

One approach is to make the output function part of the class so that it can access the results array directly. While operator<< cannot be literally part of your class, you can make it logically part of the class by declaring it a friend.

class StudentRecords {
    friend ostream& operator <<( ost& os, const StudentRecords& R);
    // Rest of the class definition
};

ostream & operator <<(ostream & os, const StudentRecords& R)
{
    for(unsigned i = 0; i < MAX_RESULTS; i++) {
        os << R.results[i] << '\n';
    }
    return os;
}

Alternatively, you could avoid friendship by defining a member function that prints the array and having operator<< call that member.

class StudentRecords {
  public:
    void print_to(std::ostream& os) const
    {
        for(unsigned i = 0; i < MAX_RESULTS; i++) {
            os << results[i] << '\n';
        }
    }
    // Rest of the class definition
};

ostream & operator <<(ostream & os, const StudentRecords& R)
{
    R.print_to(os);
    return os;
}

Note that this approach is geared toward the case where nothing else outside the class will need to access the results array. If you need external access to the array, you might as well fix your getter (as in other answers) and use that public access for printing.

烟柳画桥 2025-02-12 05:52:50

正如各个人指出的那样,解决此问题时需要考虑各种各样的事情。

  1. 对象数组的GETTER可以使用索引号(好的旧int i)来定位数组中的元素。例如,R.GetResult(i)
  2. 声明不是表达式!在我的getter中,我使用了“返回结果[max_results];其中max_results是一个恒定的数字...但这最终含义是返回max_results-th元素的数组,显然不是打算。
  3. 我将尝试尝试的一件事是为数组成员变量创建指针函数。
  4. 建议快速了解矢量,因为声明“结果结果[max_results]”;就是说,用评论员的五颜六色的话说,“ C ++和C的邪恶混合,使事情比需要更复杂的事情变得更加复杂。”

As pointed out by various people, there are various things to consider when tackling this issue.

  1. The getter for the object array can take an index number (good old int i) to target the element inside the array. e.g. R.GetResult(i)
  2. A declaration is not an expression! In my getter I used the expression "return results[MAX_RESULTS];" where MAX_RESULTS is a constant number... but this ends up meaning to return the array at the MAX_RESULTS-th element, clearly not intended.
  3. One thing for the future that I am going to try is to create a pointer function to the array member variable.
  4. It was suggested to quickly learn about vectors, since the declaration of "Result results[MAX_RESULTS];" is, to put it in the colorful words of a commentator, "an unholy mix of C++ and C that makes things more complicated than they need be further down the road."
扛起拖把扫天下 2025-02-12 05:52:50

另一种方法(并非总是一个好方法,但要牢记的方法)是保留返回数组的想法,而是从C风格数组升级到std :: Arraystd ::数组的行为很像C风格数组,但它不会腐烂到指针。这使得将数组往返函数和从功能传递变得更加容易。

    // In the class definition

    const std::array<Result, MAX_RESULTS> & GetResults() const {
        return results;
    }

  private:
    std::array<Result, MAX_RESULTS> results;

返回参考可以防止不必要的副本,并制作参考const可防止外部代码更改数据。

使用此类型的返回值,Expression r.getResults()[i]在流操作员中变得有效。实际上,您的代码中可能只需要三个更改即可使用std ::数组,并且这些更改都在上述代码块中证明。

  • 更改结果的类型
  • 更改getResults()的返回类型。
  • 拥有getResults()返回简单的结果

(虽然我还将getResults()()的定义夹住了,这只是为了我的方便,而不是修复程序的一部分。)


但是,我们仍然可以做得更好。名称max_results表明,数组中的可用结果比最大值少。使用somenumber而不是max_results操作员&lt;&lt;中支持此推断。对于在编译时不知道有用大小的数组,std :: vector是一个更合适的解决方案。

与切换到std :: Array不同,转到std :: vector的开关将需要更改某些代码,而这些代码未包含在问题的一部分。例如,可能有一种添加结果的方法。与其跟踪已存储了多少结果,将新结果分配给下一个可用点并增加计数,而是将新方法是push_back()新结果。一旦转换了所有内容,max_results常数应该不使用,因此可以消除(这是切换到向量的第一个好处)。

对于问题中的代码,更改与切换到std :: array时所做的相似。

  // In the class definition

  const std::vector<Result> & GetResults() const {
    return results;
  }

private:
  std::vector<Result> results;

std :: Array方法一样,您的运算符&lt;&lt;将在您编写时工作,假设somenumber以某种方式设置为r.getResults()。size()。但是,您可以通过切换到基于范围的循环来进一步实施。

ostream & operator <<( ostream & os, const StudentRecords& R )
{
    // Range-based looping removes the need to track indices.
    for (const auto& result : R.GetResults())
    {
        os << result << '\n';
    }
    return os;
}

这些方法的缺点是“数组”或“向量”成为界面的一部分,而不是实现细节。这是关于哪种设计的判断呼吁。就个人而言,如果需要返回矢量,我倾向于将类似类似的

    // Container used to store `Result` objects.
    using ResultContainer = std::vector<Result>;

内容放在类别中,然后替换std :: vector&lt; result&gt;resultscontainer std :: vector&gt; >。这告诉您类的用户,他们可以假设resultContainer是一个容器,并且尝试基于范围的循环,但暗示不应假设特定于矢量的功能。 (含义很弱;更好的文档会更好。)这使您可以灵活地用不同的容器替换std :: vector,如果有理由这样做。

Another approach (not always a good approach, but something to keep in mind) is to keep the idea of returning the array, but upgrade from C-style arrays to std::array. A std::array behaves a lot like a C-style array, but it does not decay to a pointer. This makes it easier to pass the array to and from functions.

    // In the class definition

    const std::array<Result, MAX_RESULTS> & GetResults() const {
        return results;
    }

  private:
    std::array<Result, MAX_RESULTS> results;

Returning a reference prevents unnecessary copies, and making the reference const prevents outside code from changing your data.

With this type of returned value, the expression R.GetResults()[i] becomes valid in your streaming operator. In fact, there might be only three changes required in your code to use a std::array, and those changes are all demonstrated in the above code block.

  • Change the type of results.
  • Change the return type of GetResults().
  • Have GetResults() return simply results.

(While I also inlined the definition of GetResults(), that was just for my convenience, not part of the fix.)


However, we can still do better. The name MAX_RESULTS suggests that there could be fewer usable results in the array than the maximum. This inference is supported by the use of SomeNumber instead of MAX_RESULTS in operator<<. For an array whose useful size is not known at compile time, a std::vector is a more suitable solution.

Unlike switching to std::array, a switch to std::vector will require changes to some of the code that was not included as part of the question. For example, there is probably a method for adding a result. Instead of tracking how many results have been stored, assigning the new result to the next available spot, and incrementing the count, the new approach would be to push_back() the new result. Once everything is converted, the MAX_RESULTS constant should be unused hence can be eliminated (this is your first benefit of switching to vectors).

For the code that is in the question, the changes are similar to what was done when switching to std::array.

  // In the class definition

  const std::vector<Result> & GetResults() const {
    return results;
  }

private:
  std::vector<Result> results;

As with the std::array approach, your operator<< will work as you wrote it, assuming SomeNumber is somehow set to R.GetResults().size(). You could, though, take the implementation one step further by switching to a range-based loop.

ostream & operator <<( ostream & os, const StudentRecords& R )
{
    // Range-based looping removes the need to track indices.
    for (const auto& result : R.GetResults())
    {
        os << result << '\n';
    }
    return os;
}

The downside of these approaches is that "array" or "vector" becomes part of the interface rather than an implementation detail. It is a judgment call as to which design is preferable. Personally, if returning a vector is desirable, I would be inclined to put something like

    // Container used to store `Result` objects.
    using ResultContainer = std::vector<Result>;

in the class definition, then replace all other uses of std::vector<Result> with ResultContainer. This tells users of your class that they may assume ResultContainer is a container and attempt range-based looping over it, but implies that vector-specific functionality should not be assumed. (Implications are weak; better documentation would be better.) This gives you the flexibility to replace std::vector with a different container, if there is ever a reason to do so.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文