How to properly access members in constructor using set and get methods

Hello, i searched a lot on how to properly do that, but it seems like i am stuck on very simple task and the code below is absurd.

The variables are private then i created constructor for the class. Later in the main function i am trying to access and change the variables using set method, but it seems like no matter how i write the constructor i can't access it because it says it doesn't exist or these "<<", "=" operators can't be used on certain variables. I tried to populate with data using "std::cin>>" which gave me an error.

This is part of the assignment:

For class Country write:
constructors
get and set methods
input method to populate object country
predefine operations for comparison(<, >) of two countries by name and the operation for << in the stream.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
#include <string>
#include <iostream>
#include <vector>

using namespace std;


class Country {

private:
    string name, continent;
    int population;
    vector<string> cities;

public:


    Country() : name(" "), continent(" "), population(0), cities(0)
    {  }

    void setName(string n) {
        name = n;
    }



    string getName() {

        return name;
    }


    
};





int main() {

    Country n, c, p, ct;

    std::cout << "Enter Country:";

    std::cin >> n.SetName();
Last edited on
show us exactly what you are trying to run.
the posted version has a mismatch in case, so line 71 fails it.
you can't cin to a function this way (to do that it would need to return a direct reference to the data, making the getter function moot -- its doable, but not cleanly).
so ..
string & country::globalize_name()
{
return name; //returns a reference to this
}
should let you say
cin >> globalize_name(); //this is very bad code. but you can do just about anything in c++ even when you should not!
if you want this, spare us the clutter and make name public. then its just
cin >> var.name

consider this, does it answer or help your issues?
1
2
3
4
5
6
7
8
9
10
11
12

int main() {

    Country n, c, p, ct;

    std::cout << "Enter Country:";

    string s{"USA"};
     n.setName(s);
     cout << n.getName();
}


the bottom line is that things need to match up.
you have a method that takes a string, so you need to give it a string.
its the same thing as if it were not in a class.
you have this, with the class-gibbersh removed:

void foo (string s); //some function out there etc
..
cin >> foo(); //compiler is going to hate on this with all kinds of exciting messages.

the first tier (no inheritance, virtual, or other concepts) of OOP / classes works just like normal programming ... the methods are just like normal functions, except that have access to some "global to them" variables (the class's member variables). The fancy stuff moves beyond this a little but its still 'very like this' even when you get to the second tier studies.
Last edited on
Thank you! Yeah that cleared things a bit.

It works now since i made it public and used your example to store the string and then assign it using "set()".

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43

#include <string>
#include <iostream>
#include <vector>


using namespace std;


class Country {

public:
    string name, continent;
    //int population;
    //vector<string> cities;


    Country() {  }

    void setName(string n) {
        name = n;
    }


    string getName() {

        return name;
    }
};


int main() {

    Country n;
    string s{ " " };


    cout << "Enter Country:";
    cin >> s;
    n.setName(s);
    cout << n.getName();
}



But now for the vector string what will be the right way to fill it with data? Something like this?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51

#include <string>
#include <iostream>
#include <vector>


using namespace std;

const int cinTerminator = -1;

class Country {

public:

    string cities_names;
    vector<string> cities;


    Country() {  }

    void setName(string n) {
        cities_names = n;
    }


    string getName() {

        return cities_names;
    }
};


int main() {

    Country n;
    string city{ " " };


    
     while ((cin >> city) && city != cinTerminator) {
        n.push_back(city);
    }
    
      n.setName(city);
     
}




Last edited on
Hello georgio,

Your subject:

How to properly access members in constructor using set and get methods


Leads me to believe that you are misunderstanding how the constructor, (ctor for short), works.

The ctor is invoked when you define an object of the class, as you do in "main". After that you do not call the ctor to set any of the private variables of the class. That is what the set functions are for.

Looking at your code a "std::string" and "std::vector" are empty when defined and have no size, so they do not need initialized unless you want to give them a starting value.

In the initialization list of the default ctor all you need is Country() : population(0) {}. Initializing the strings to a space is not necessary and cities(0) does nothing, it is still empty with a (0)zero size.

The rest of the public functions appear to be correct, but I have not had a chance to test them yet because "main" needs reworked.

In "main" you start with: Country n, c, p, ct;. This is a bit confusing because you have already used these letters in your class functions. Also single letter variable names have no to little meaning to any one but you. This line of code defines 4 objects of type "Country". You only need 1 object at least to get started with. If you need more later that is fine, but give them a better name than just a single letter.

The prompt is OK, but I put a space after the colon.

jonnin has already covered the "cin".

So your "main" function could look something like this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
int main()
{
    int population{};         // <--- ALWAYS initialize all your variables.
    std::string countryName;  // <--- Strings are empty when defined and do not need initialized.
    std::vector<std::string> cities;

    Country country;

    std::cout << "Enter Country: ";
    std::cin >> countryName;

    std::cout << "Enter population: ";
    std::cin >> population;

    std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');  // <--- Requires header file <limits>.
    
    country.setName(countryName);
    country.setPopulation(population);

    for (std::string city; ;)
    {
        std::cout << "\nEnter a city (blank to end): ";
        std::getline(std::cin, city);

        if (city.empty())
            break;

        cities.emplace_back(city);
    }

    country.setGradove(cities);

    return 0;  // <--- Not required, but makes a good break point for testing.
}

Sorry about that, after I tested this code I realized I missed input for "continent". Easy enough to add.

That should give you some idea of what you need to do.

Andy
for the vector you could have a constructor or setter, and copy an input vector to your class storage.
you can also have an add-name, that does a push_back().

the question on how to populate it is tied to how you want to use it. Its oversimplified, but one way to build a smaller class is to simply start using it in code somewhere, even if it does not exist, you type in the things you WANT to be able to do (maybe you assign it, so that means you need assignment operator, maybe you want to set things, you need setters, and so on). Tally up what you need and look for a theme (if you have an operator +, maybe you need operator - even if you did not use it in the fake code) or rules (do you know the rules of 3, 5, etc?).
that can help you quickly nail down what you need, and with practice, you will leave out less and less stuff after doing it a few times.
As a starter, consider:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
#include <string>
#include <iostream>
#include <vector>

class Country {
private:
	std::string name, continent;
	int population {};
	std::vector<std::string> cities;

public:
	Country() {}
	Country(std::string& nam, int pop, std::string& cont) : name(nam), population(pop), continent(cont) {}

	void setName(const std::string& n) { name = n; }
	std::string getName() const { return name; }
	void setContinent(const std::string& c) { continent = c; }
	std::string getContinent() const { return continent; }
	void setPop(int pop) { population = pop; }
	int getPop() const { return population; }
	void addCity(std::string& city) { cities.emplace_back(city); }
	auto getCities() const { return cities; }
};

std::ostream& operator<<(std::ostream& os, const Country& c)
{
	os << "\nName: " << c.getName() <<
		"\nPopulation: " << c.getPop() <<
		"\nContinent: " << c.getContinent() <<
		"\nCities:\n";

	for (const auto& ci : c.getCities())
		os << ci << "  ";

	return os << '\n';
}

int main() {
	std::string nam, cont;
	int pop;

	std::cout << "Enter Country name: ";
	std::getline(std::cin, nam);

	std::cout << "Enter Continent name: ";
	std::getline(std::cin, cont);

	std::cout << "Enter population: ";
	std::cin >> pop;
	std::cin.ignore();

	Country c(nam, pop, cont);

	for (std::string city; std::cout << "Enter city (<CR> to terminate): " && std::getline(std::cin, city) && !city.empty(); c.addCity(city));

	std::cout << c << '\n';
}


The comparisons need to be added.
Hello Handy Andy,

And yes indeed i was misunderstanding the ctor and thanks for the detailed explanation and the code example, because that cleared up things for me! And i don't know how i missed the initialization of the int variable, thinking the problem was in the way i put parameters to the ctor.

Hi jonnin,

Yes indeed practice is important and i haven't done that in a while, that's why it was a mess in my head and i didn't know how to begin.

Absolutely, thanks seeplus!

I had to read about some things, so i could understand more clearly what happens in the code.

In the constructor why did you add the "name(nam)" isn't it enough to just put them in the scope of the first parentheses?

So i think i can mark this as solved because that cleared things for me on how to properly use some methods and functions!
Last edited on
Hello georgio,

You are welcome.


In the constructor why did you add the "name(nam)" isn't it enough to just put them in the scope of the first parentheses?


No. The variables defined in the () are the same as variables defined in a regular function. They are local variables that can be used to do something. For a ctor the parameters of the ctor are used to give the variables of the class a value when an object of the class is constructed.

At one time the overloaded ctor was written as:
1
2
3
4
5
6
7
Country (const std::string& inName, const std::string& inContienent, const int inPopulation, const std::vector<std::string>& inCities)
{
    name = inName;
    continent = inContienent;
    population = inPopulation;
    cities = inCities;
}

Looks like any normal function.

Then came the initialization list:
 
Country(std::string& nam, int pop, std::string& cont) : name(nam), population(pop), continent(cont) {}

In this case "name" is the variable in the class and "nam" is the parameter sent to the ctor. It is a shorter way to give the class variables a value when the ctor is called with less work.

The initialization list is preferred over the old style, but the old style still works.

Andy
Topic archived. No new replies allowed.