0
votes

I know my message is not properly formattd, but I'm new so please help me anyway. I have two classes: Father and Son. In Son I have an int and a string. In father i have a vector of son objects. How can I access just the part of the vector composed by integers and/or the part just composed by strings? Thank you very much!


CLASS SON.H

#ifndef SON_H
#define SON_H
#include <iostream>
using namespace std;

class Son
{
    public:
        Son() {}
        Son(int first, string second);
        virtual ~Son();
        int getFirst() const;
        string getSecond() const;
    private:
        int _first_parameter;
        string _second_parameter;
};

#endif // SON_H

CLASS SON.CPP

#include "son.h"

Son::Son(int first, string second)
{
    _first_parameter=first;
    _second_parameter=second;
}

Son::~Son()
{
    //dtor
}

int Son::getFirst() const
{
    return _first_parameter;
}

string Son::getSecond() const
{
    return _second_parameter;
}

CLASS FATHER.H

#ifndef FATHER_H
#define FATHER_H
#include <vector>
#include "son.h"

class Father
{
    public:
        Father() {}
        virtual ~Father();
        void filling();
    private:
        vector<Son> _access_vector;
        void _printIntegers(vector<int> v);
        void _printStrings(vector<string> v);
};

#endif // FATHER_H

CLASS FATHER.CPP

#include "father.h"

Father::~Father()
{
    //dtor
}

void Father::filling()
{
    int temp_first_param;
    string temp_second_param;
    cout<<"Insert integer: "<<endl;
    cin>>temp_first_param;
    cout<<"Insert text"<<endl;
    cin>>temp_second_param;
    _access_vector.push_back(Son(temp_first_param, temp_second_param));
    _printIntegers(_access_vector.getFirst());                       /// Here I want to take just the vector of integers
    _printStrings(_access_vector.getSecond());                       /// Here I want to take just the vector of strings
}

void Father::_printIntegers(vector<int> v)
{
    for(unsigned i=0; i<v.size(); ++i)
        cout<<v[i]<<endl;
}

void Father::_printStrings(vector<string> v)
{
    for(unsigned i=0; i<v.size(); ++i)
    {
        cout<<v[i]<<endl;
    }
}

COMPILER ERRORS:

||=== Build: Debug in Vector_access_experiment (compiler: GNU GCC Compiler) ===| C:\Users\Alessandro\Documents\CodeBlocks\Vector_access_experiment\src\father.cpp||In member function 'void Father::filling()':| C:\Users\Alessandro\Documents\CodeBlocks\Vector_access_experiment\src\father.cpp|17|error: 'class std::vector' has no member named 'getFirst'| C:\Users\Alessandro\Documents\CodeBlocks\Vector_access_experiment\src\father.cpp|18|error: 'class std::vector' has no member named 'getSecond'| ||=== Build failed: 2 error(s), 0 warning(s) (0 minute(s), 0 second(s)) ===|

2
Reviewing what is provided with std::vector vs. what you're trying to do with it, those errors make perfect sense. Those errors are nothing if not self explanatory; there are no getFirst and getSecondmethod in std::vector. - WhozCraig
There is no "just the part of the vector composed by integers" so you cannot access any such thing. - n. 1.8e9-where's-my-share m.
getFirst and getSecond are methods of the Son class, not of std::vector class. You have to get the object from vector before trying to access its methods. - Hải Phạm Lê

2 Answers

2
votes

Actual answer was given in the comments, now how to solve your problem at hand and some explanation:

std::vector wraps an array. Which means, in the memory, the data within the vector is consecutive. vec[6] lies at the position of vec[5] + sizeof(type) in memory.

In your case, since Son stores a string and an int, this means that the memory looks like this:

int of entry 0, string length of entry 0, string char pointer of entry 0, int of entry 1, string length of entry 1...

What you try to get is a structure that looks like this:

int of entry 0, int of entry 1, ...

Which is obviously not in there. Creating it will require computation time, no way around that.

Since your method printIntegers copies some vector anyway (because you don't call by reference), you can simply solve this by creating new vectors that store the partial data by iterating over the original vector, but that is bad design.

I'd propose:

void Father::_printIntegers(const vector<Son>& v) const
{
    for(unsigned i=0; i<v.size(); ++i){
        cout<<v[i].getFirst()<<endl;
    }
}

(also added call by reference and const keyword, use those!)

You could also merge Son into Father, creating two vectors within Father, which might make sense in some scenario, depends on your context.

That said, as for your design - if there is a hard separation of Son into integers and strings, Son might be a weak class. Classes are not meant to be mere data holders. The best thing would be that Son does the printing itself. Father should have no knowledge about what members Son has - understand what I mean? That said, also depends on context, sometimes mere data holders is what you want.

edit: some comment to my answer raised a valid point, here the method without parameters:

void Father::_printIntegers() const
{
    for(unsigned i=0; i<v.size(); ++i){
        cout<<_access_vector[i].getFirst()<<endl;
    }
}
1
votes

You can't call

_access_vector.getFirst()
_access_vector.getSecond()
_access_vector.at(i).getFirst();
_access_vector.at(i).getSecond();

which i is position of your object in std::vector.