【问题标题】:A private vector of pointers pointing to objects. How to access those objects with getter method?指向对象的指针的私有向量。如何使用 getter 方法访问这些对象?
【发布时间】:2013-04-16 06:03:04
【问题描述】:

我的程序是一个循环的六次迭代,其中八个人互相投票。每个人在每次迭代中投票给谁,保存到私有类成员voteList(指针向量)。

我的麻烦是,在六次迭代结​​束时,我希望能够使用我编写的GetVote(int) public 方法说,例如,安娜在每次投票中投票给了谁。

*(voteList[round]) 应该是 Anna 在给定回合中投票给谁的价值(一个人),我想?并且使用GetName() 方法应该检索该人姓名的字符串。但无论我怎么摆弄它,每当我调用GetVote() 时程序就会崩溃。

我确信我犯了一个或多个非常愚蠢的错误,但我不知道问题出在哪里。任何意见将不胜感激!

#include <iostream>
#include <vector>
#include <random>
#include <time.h>
using namespace std;

enum gender { male, female };

class Person {
    private:
        string personName;
        gender personGender;
        vector<Person *> voteList;
    public:
        // Constructors
        Person (string, gender);
        // Setters
        void Vote (Person * target) {
            voteList.push_back (target); 
        };
        // Getters
        string GetName () { return personName; };
        string GetVote (int round)
        {
            Person ugh = *(voteList[round]);
            return ugh.GetName ();
        };
};

Person::Person (string a, gender b) {
    personName = a;
    personGender = b; }

void Voting (vector<Person> voters)
{
    for (int i = 0; i < voters.size(); i++) {
        int number = (rand() % voters.size());
        Person * myTarget = &voters[number];
        voters[i].Vote (myTarget);
        cout << voters[i].GetName() << " votes for " << voters[number].GetName() << endl;
    }
    cout << endl;
}

int main()
{
    srand(time(0));

    Person Anna ("Anna", female);
    Person Baxter ("Baxter", male);
    Person Caroline ("Caroline", female);
    Person David ("David", male);
    Person Erin ("Erin", female);
    Person Frank ("Frank", male);
    Person Gemma ("Gemma", female);
    Person Hassan ("Hassan", male);

    vector<Person> theGroup;
    theGroup.push_back (Anna);
    theGroup.push_back (Baxter);
    theGroup.push_back (Caroline);
    theGroup.push_back (David);
    theGroup.push_back (Erin);
    theGroup.push_back (Frank);
    theGroup.push_back (Gemma);
    theGroup.push_back (Hassan);

    for (int n = 0, iterations = (theGroup.size() - 2); n <= iterations; n++)
        Voting (theGroup);

    cout << "ANNA VOTED FOR...";
    for (int n = 0; n <= 5; n++)
    {
        cout << "Round " << (n + 1) << ": " << Anna.GetVote(n) << '\n';
    }

    cin.ignore();
    return 0;
}

【问题讨论】:

  • afaik std::vector 将在堆上分配对象,因此分配内存来存储指向另一个堆空间的指针是没有意义的。但无论如何...您的GetVote(int) 成员需要检查round 是否小于或等于您的voteList 的对象数。其余的由 Nbr44 解释;)

标签: c++ pointers methods vector getter


【解决方案1】:

当您调用voting 时,您传递了向量的副本,内容也将被复制。

您应该将此向量作为参考传递:

void Voting (vector<Person>& voters) { ... }

您可能还想在 GetVote 中添加一些安全检查,以确保调用者不会提供超出范围的索引。

【讨论】:

  • 谢谢!除其他外,这是缺乏参考。很好地呼吁安全检查,现在就开始工作。
【解决方案2】:

首先,您要在各处复制您的Person 对象。例如,将您的 Person 对象添加到 theGroup 向量并再次将同一向量传递给 Voting 函数时。

复制人物在语义上没有任何意义。为了避免这种情况,您应该在 Person 类中添加私有复制构造函数和赋值运算符:

private:
    Person(const Person& other);
    Person& operator=(const Person& rhs);

接下来,您将不得不更改向量以使用 Person 指针:

    vector<Person *> theGroup;
    theGroup.push_back (&Anna);
    theGroup.push_back (&Baxter);
    theGroup.push_back (&Caroline);
    theGroup.push_back (&David);
    theGroup.push_back (&Erin);
    theGroup.push_back (&Frank);
    theGroup.push_back (&Gemma);
    theGroup.push_back (&Hassan);

您可以使用-&gt; 运算符来调用指向对象的指针的方法,如下所示:

    string GetVote (int round)
    {
        Person *ugh = voteList[round];
        return ugh->GetName ();
    };

还有:

void Voting (const vector<Person *>& voters)
{
    for (int i = 0; i < voters.size(); i++) {
        int number = (rand() % voters.size());
        Person *myTarget = voters[number];
        voters[i]->Vote (myTarget);
        cout << voters[i]->GetName() << " votes for " << voters[number]->GetName() << endl;
    }
    cout << endl;
}

【讨论】:

  • 啊,效果很好,谢谢!我什至没有意识到我正在复制我的对象。您可能会说,我对此很陌生。 :(
【解决方案3】:
void Voting (vector<Person> voters)

您想将此作为参考。否则,当您获得 voters[number] 的地址时,您将获得函数的局部变量的地址 - 一旦您尝试实际使用它,一切都会变得很糟糕。

void Voting (vector<Person> &voters)

实际上这并不是问题所在,尽管这仍然与引用有关。 您正在通过副本传递原始vector,这意味着原始vector(在main 函数中)不会被函数的操作修改(当然,其内容也是如此)。所以,里面的所有Persons 都有它们的原始状态,一个空的voteListvector。 显然,如果您尝试取消引用它的任何(不存在的)元素,那将不会顺利!

【讨论】:

  • 我对所有内容进行了重新设计,以便它指的是原件而不是副本,它的工作方式就像一个魅力。谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-10-01
  • 1970-01-01
  • 1970-01-01
  • 2017-09-14
  • 2011-02-11
  • 1970-01-01
相关资源
最近更新 更多