【问题标题】:How to work with the C++ class members individually and at the same time as a whole?如何单独和同时与 C++ 类成员一起工作?
【发布时间】:2021-06-13 22:43:21
【问题描述】:

我有以下 C++ 代码

矩形.h

class Rectangle {
public:
    Rectangle(int _id);
    void draw();
    int getId();
private:
    int id;
};

矩形.cpp

#include "Rectangle.h"
#include <iostream>

Rectangle::Rectangle(int _id) {
    id = _id;
}
void Rectangle::draw() {
    std::cout << "Drawing rectangle with id: " << id << std::endl;
}

int Rectangle::getId() {
    return id;
}

矩形集合.h

#include "Rectangle.h"

class RectanglesCollection {
public:
    Rectangle rectangle_00;
    Rectangle rectangle_01;
    Rectangle rectangle_02;
    Rectangle rectangle_03;
        
    RectanglesCollection();
        
    void update();
};

矩形集合.cpp

#include "RectanglesCollection.h"

RectanglesCollection::RectanglesCollection() : 
rectangle_00(10),
rectangle_01(20),
rectangle_02(30),
rectangle_03(40)
{}
    
void RectanglesCollection::update() 
{
    rectangle_00.draw();
    rectangle_01.draw();
    rectangle_02.draw();
    rectangle_03.draw();
}

main.cpp

#include "Rectangle.h"
#include "RectanglesCollection.h"
#include <cstdlib>
#include <iostream>

using namespace std;

int main(int argc, char** argv) {

    RectanglesCollection rectangles;
    rectangles.update();
    
    std::cout << "Id of the first rectangle in collection of rectangles: " << rectangles.rectangle_00.getId() << std::endl;
    
    return 0;
}

我的问题是,我是否有可能避免在 RectanglesCollection::update 方法中重复代码,而不是直接在单个 Rectangle 成员上方使用一些循环迭代?如果集合的用户除了定义Rectangle 类的实例之外不需要做任何其他事情,那将是理想的。同时,我想保留与 Rectangle 成员单独合作的可能性,例如 rectangles.rectangle_00.getId()

【问题讨论】:

  • 使用向量(如果元素的数量可以在运行时改变)或数组?
  • 您通常会遍历数组或其他容器。只需将您的矩形放在某种容器中并循环它。
  • 您正在寻找数组。

标签: c++ loops collections iteration


【解决方案1】:

如果您在 RectanglesCollection 中将 Rectangle 成员变量表示为 std::array&lt;Rectangle, 4&gt;,则可以通过索引和 operator[](size_t) 访问器成员函数轻松访问它们。

#include <array>
#include <cstddef>
#include <iostream>
#include <stdexcept>

using std::array;
using std::cout;
using std::ostream;
using std::out_of_range;
using std::size_t;

// NAME_OF for String-ify.
#define NAME_OF(x) #x

class Rectangle {
    int _id;
public:
    Rectangle(int id);
    void draw(ostream&) const;
    auto id() const -> int;
};

Rectangle::Rectangle(int id_) : _id{id_} { }

void Rectangle::draw(ostream& out) const {
    out << "Drawing rectangle with id: " << id() << "\n";
}

auto Rectangle::id() const -> int {
    return _id;
}

class RectanglesCollection {
    array<Rectangle, 4> rectangles = {10, 20, 30, 40};
public:
    auto operator[](size_t i) const -> Rectangle;
    void display() const;
};

auto RectanglesCollection::operator[](size_t i) const -> Rectangle {
    if (i >= rectangles.size())
        throw out_of_range(NAME_OF(i));

    return rectangles[i];
}

void RectanglesCollection::display() const {
    for (auto&& r : rectangles) {
        r.draw(cout);
    }
}

int main() {
    auto rectangles = RectanglesCollection();
    rectangles.display();
    cout << "Id of the first rectangle in collection of rectangles: " << rectangles[0].id() << "\n";
}

【讨论】:

  • 感谢您的回复。您建议的解决方案也出现在我的脑海中。但是有一些我想避免的缺点。首先,我需要使用像rectangles[0] 这样的矩形而不是rectangle_xyz,即我需要记住特定矩形放置在哪个索引处。第二个问题是我需要指定能够分配数组的矩形数量。正如我在问题中提到的那样,我想以某种方式自动化该任务。也许以某种方式通过sizeof 运算符。
  • @ProfessorJimatura • 您可以创建一个auto rectangle_xyz() const -&gt; Rectangle { return rectangles[0]; } 访问器成员函数来命名索引,并使用这些函数,而不必记住具有某些元语义的特定索引位置。如果矩形的数量是可变的,std::vector 会更适合,但这很难与专门命名的成员函数访问器协调。使用template 参数化可能更适合自动化任务。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-01-10
  • 1970-01-01
  • 2018-12-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多