Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Two types of value in one vector C++

Tags:

c++

vector

Say I have a vector for class Students, but the requirement of the question states that I cannot put grade together in the constructor, so I will have to work around it.

Is it possible that I have two values in one vector slot?

For example, the class Student and string grade are my arguments.

vector<Student*, string> Students;

So, at the end of the day, if I cout the vector, I should get Student AND the grade in one slot.

Does this work? If so, how do I push_back the value?

Otherwise, is there another way to do this?

like image 908
Timothy Wong Avatar asked Jan 11 '16 15:01

Timothy Wong


People also ask

Can a vector have different data types?

Yes it is possible to hold two different types, you can create a vector of union types. The space used will be the larger of the types.

Can a vector contain multiple data types?

A vector will hold an object of a single type, and only a single type.

What are the vectors in C?

Vectors are the dynamic arrays that are used to store data.It is different from arrays which store sequential data and are static in nature, Vectors provide more flexibility to the program. Vectors can adjust their size automatically when an element is inserted or deleted from it. Vectors are not ordered in C++.

Does vector double its size?

This happens because every time we run out of capacity, the vector doubles its capacity. Therefore, if we insert one element when the capacity of the vector is 1 , the vector will double its size to 2 . If we insert one more element, the vector will double its size to 4 .


2 Answers

std::vector<std::pair<Student*, string>> students;

or even better:

std::map<Student*, string> students;

Pushing values:

first case:

students.push_back(std::make_pair(x,y));

even better(as @snps advised):

students.emplace_back(x, y);

second case:

students[x]=y;

Be aware that in the second case you can not add multiple record with the same Student* value. If you try it will write over the old one.

like image 65
Humam Helfawi Avatar answered Oct 05 '22 00:10

Humam Helfawi


There are multiple ways of achieving this.

A. Array of structures:

A1. Composition:

class GradedStudent {
    Student body;
    string grade;
    public:
    GradedStudent(const string& grade);
    // reimplement all methods of `Student`, 
    // delegating implementations to `body`
};

std::vector<GradedStudent> gradedStudents;

A2. Inheritance (all students have grades):

class Student {
public:
    Student();
};

class GradedStudent {
    string grade;
public:
    GradedStudent(const string& grade);
};

std::vector<GradedStudent*> gradedStudents;

A3. Inheritance + polymorphysm (some students have grades and some don`t):

class Student {
public:
    Student();
    virtual ~Student();
    virtual const string& getGrade() const { return ""; }
};

class GradedStudent : public IStudent {
    string grade;
public:
    GradedStudent(const string& grade);
    virtual string getGrade() const override { return grade; }
};

std::vector<Student*> students;
// non graded students will have empty string as a grade

B. Structure of Arrays approach (separate array for grades):

std::vector<Student*> students;
std::vector<string> grades;

for(int i = 0; i < students.size(); ++i) {
    auto* student = students[i];
    auto grade = grades[i];
}

C. Associative container (doesn`t honor "use std::vector" requirement):

std::map<Student*, string> students;

for(auto student : students) {
    auto* student = student.first;
    auto grade = student.second;
}

Those are classic ones. There might be more.

If all students have grades, you should really make grade a member of this class.

P.S. Do you really need to store pointers in a vector (as opposed to storing objects)?

like image 30
Ivan Aksamentov - Drop Avatar answered Oct 04 '22 22:10

Ivan Aksamentov - Drop