I'm currently working on my first project using classes and objects, and I've run into a bit of a roadblock with my setter. I made up an example to illustrate the issue I'm running into (all one file for the sake of simplicity).
#include <stdio.h>
#include <iostream>
#include <string>
using namespace std;
class Example1
{
public:
Example1() { name = "Mike"; }
Example1(string aName) { name = aName; }
string GetName() const { return name; }
void SetName(string newName) { name = newName; }
private:
string name;
};
class Example2
{
public:
Example2() : anObj() {}
Example2(string aName) : anObj(aName) {}
Example1 GetObj() const { return anObj; }
void SetObj(string objName) { anObj.SetName(objName); }
private:
Example1 anObj;
};
int main()
{
Example2 myObj;
cout << myObj.GetObj().GetName() << endl;
myObj.GetObj().SetName("Stan");
cout << myObj.GetObj().GetName() << endl;
}
Output:
Mike
Mike
The idea is to alter the member object in Example2 by using the member object's setter method, but the setter method doesn't seem to be working the way I expected.
I tried accessing the member by moving it to public (in Example2) and using dot notation, and that successfully changed the name. I'm not sure what the differentiation is, but, since the getter is working properly, I feel like something is wrong with how I'm using the setter.
The original problem I was trying to solve was having a Game class with a Player class member object. The idea is that the player could change their name if they wanted to.
Appreciate any help. Thanks.
All your getters return a new object. Don't. Let them return a const &. But then you need a non const getter when you modify objects to call the setters:
const Example1& GetObj() const;
Example1& GetObj();
And now, the objects that are stored underneath will be updated, and not just their copies. Same for the strings.
You can also see the fact that the setters are not working on the proper objects by using a debugger.
Related
I have recently started learning OOP in C++ and I started solving example tasks regarding it. I want to instantiate an object of the class CStudent after having created a default constructor for it. However the compiler cannot compile the code. I would like to ask why is that?
When you write inside your class:
CStudent();
CStudent(string name, string fn);
...you only declare two constructors, one default (taking no-argument) and one taking two strings.
After declaring them, you need to define them, the same way you defined the methods getName or getAverage:
// Outside of the declaration of the class
CStudent::CStudent() { }
// Use member initializer list if you can
CStudent::CStudent(std::string name, string fn) :
name(std::move(name)), fn(std::move(fn)) { }
In C++, you can also define these when declaring them inside the class:
class CStudent {
// ...
public:
CStudent() { }
CStudent(std::string name, string fn) :
name(std::move(name)), fn(std::move(fn)) { }
// ...
};
Since C++11, you can let the compiler generate the default constructor for you:
// Inside the class declaration
CStudent() = default;
This should work, As commented by Holt, You need to define constructor, You have just declared it.
#include <iostream>
#include <string>
#include <list>
using namespace std;
class CStudent {
string name = "Steve";
list<int> scores;
string fn;
public:
CStudent() {};
CStudent(string name, string fn);
string getName();
double getAverage();
void addScore(int);
};
string CStudent::getName() {
return name;
}
double CStudent::getAverage() {
int av = 0;
for (auto x = scores.begin(); x != scores.end(); x++) {
av += *x;
}
return av / scores.size();
}
void CStudent::addScore(int sc) {
scores.push_back(sc);
}
int main()
{
CStudent stud1;
cout<< stud1.getName()<< endl;
return 0;
}
I am trying to understand delegation in c++. I read that "delegation is pointer to function", and i saw several examples, but unfortunately I cant get it. I have created code to try, because I thought that maybe while programming i will understand it. Unfortunately I didn't.
#include <iostream>
using namespace std;
class person{
private:
int age;
public:
person(age){
this->age = age;
}
// virtual void changeAge(int arg) = 0;
};
class addNumber {
public:
int changeAge(int arg) {
arg += arg+1;
}
};
int main(){
person Olaf;
}
So based on this source I tried:
Olaf = &addNumber::changeAge(10);
or
addNumber test;
Olaf = &addNumber::changeAge(10);
Both does not work. That means program is not compiling.
I want to make person object to use changeName of addNumber class method to change the age of instance person class.
First, let's use a typedef for the function:
typedef int agechanger(int);
this makes a new type, agechanger, which will be used in code for passing the function instances around.
Now, you should give your person class a proper constructor, and properly incapsulate the age field providing a public getter. Then add a method that accepts a function as argument, function of type agechanger, of course.
class person
{
private:
int age;
public:
person(int age){
this->age = age;
}
int getAge() const {
return age;
}
void changeAge(agechanger f)
{
age = f(age);
}
};
Then define a function that fits our type, inside a class:
class addNumber {
public:
static int changeAge(int arg) {
return arg + 1;
}
};
Notice that the function is marked as static and returns the passed int incremented by one.
Let's test everything in a main:
int main()
{
person Olaf(100); //instance of person, the old Olaf
Olaf.changeAge(addNumber::changeAge); //pass the function to the person method
std::cout << Olaf.getAge() << std::endl; //Olaf should be even older, now
}
Let's make and use a different function, ouside a class, this time:
int younger(int age)
{
return age -10;
}
int main(){
person Olaf(100);
Olaf.changeAge(younger);
std::cout << Olaf.getAge() << std::endl; // Olaf is much younger now!
}
I hope that having code that works is going to help you understand things better. The topic you're asking about, here, is generally considered advanced, while I think you should review some more basic topics of c++, first (functions and classes, for example).
In C++11 and later you have closures (e.g. thru std::function etc...) and lambda expressions (that is, anonymous functions)
But you don't exactly have delegation in C++, even if you also have pointers to functions and pointers to member functions. But closures and lambda expressions are nearly equivalent, in power of expression, to delegation.
You should read SICP then some good C++ programming book to understand these notions.
Please read the question before marking it as a duplicate.
So here is what I am trying to achieve. Basically I have a string which contains some value initially.
I have split my program into many classes for modularity.(you can suggest a better way to do that - currently each file contains one class in it) So say for eg I want to operate on the data with class1 , then the modified string needs to get operated by class2 and so on.
eg.
Initial entry is "hello world"
first class -> "hello WORLD"
second class -> "H#l#o WORLD"
thiid class -> "##l#o WORLD"
and so on...
Reading everywhere that global variables are a big no no when coming to issues and downsides it has. So keeping that in mind what would be the best way I can share seamlessly between classes.
I also thought of passing the string as a pointer to each function but I thought there might be better alternatives to it. Please suggest.
Thanks for stopping by to read my que and help me out.
Without knowing exactly why you want to do this it is hard to answer. But I don't see what is wrong with just passing the string as a reference to each class much like you suggest:
class StringModifier1 {
public:
void operator()(std::string& s) {
// modify s...
}
};
class StringModifier2 {
public:
void operator()(std::string& s) {
// modify s...
}
};
class StringModifier3 {
public:
void operator()(std::string& s) {
// modify s
}
};
int main() {
std::string myString = "hello world";
StringModifier1 modifier1;
StringModifier2 modifier2;
StringModifier3 modifier3;
modifier1(myString);
modifier2(myString);
modifier3(myString);
}
Live demo.
In some cases you might want the classes to store a pointer or reference to the string:
class StringModifier1 {
private:
std::string& s;
void func1() {
// modify s...
}
void func2() {
// modify s some more...
}
public:
StringModifier1(std::string& s) : s(s) {}
void execute() {
func1();
func2();
}
};
int main() {
std::string myString = "hello world";
StringModifier1 modifier1(myString);
modifier1.execute();
StringModifier2 modifier2(myString);
modifier2.execute();
StringModifier3 modifier3(myString);
modifier3.execute();
}
Live demo.
You might want one class to own and provide access to the string and the other classes have a pointer or reference to the owning class.
can someone tell me how can i add data into my list of class with C++
please ?
#include <string>
class Person
{
private:
std::string Name;
public:
Person();
~Person();
std::string GetName()
{
return Name;
}
std::string SetName(std::string name)
{
name = Name;
return name;
}
};
void main()
{
list<Person> lp = new list<Person>();
Person p = new Person();
p.Name = "Smith";
lp.insert(p);
}
this is my attempt. Can someone correct me or give me another answer ? Thanks
If by some chance you are using c++11 or greater, consider using:
list.emplace_back()
or
list.emplace_front()
which handles construction and insertion. Of course this would be even better if you had a Person constructor that took a string argument.
Person::Person(std::string& name) { Name = name; }
In which case you could do:
lp.emplace_back("Smith");
list.insert() takes an iterator, i.e. position at which you want to insert the new element.
You can also do
list.push_back(p);
This inserts 'p' at the end of the list.
If you do
list.push_front(p);
insertion happens at the head of list.
First of all, since you're coding in c++ your main function should return an int:
int main()
Second, you're using the new keyword on an object that isn't a pointer, correct that:
// This would perhaps be better:
list<Person*> lp;
Person *p = new Person; // remember to delete p; later
I don't see that you have included <list> header and using std. You need that in order to use list. Or at least write std::list or using std::list;
You are trying to assign to a private class member, either declare it public, or use a setter function:
p->Name = "Smith"; // remember for pointers, use the '->' or *(p).Name
emplace_back() is maybe what you are looking to use (since c++11):
lp.emplace_back(p);
// otherwise, specify an iterator as first argument for insert:
// lp.insert(lp.end(), p);
Why isn't your SetName only void and needs to return something? If you want to return the new Name, you also should have
Name = name;
return Name;
You have switched it.
Also, you don't need any of the new and every main function should return int value (usually 0 if no error occurred).
FIXED CODE:
#include <string>
#include <list>
class Person
{
private:
std::string Name;
public:
//Person();
//~Person();
std::string GetName()
{
return Name;
}
void SetName(std::string name)
{
Name = name;
}
};
int main()
{
std::list<Person> lp;
Person p;
p.SetName("Smith");
lp.push_back(p);
return 0;
}
You need to include lists in order to use them, and you can't assign a private member directly. Also, your declarations are wrong - for this I would recommend some cpp tutorials and reading the documentation.
I'm new to the site (and to programming) so I hope I post this question appropriately and under all the proper guidelines of the site. Ok, here it goes:
So I pretty new to C++ and am trying to create classes for a program. I have to construct "container and entity classes", but where I'm struggling is trying to nail down the proper syntax for my getter and setter functions in the container class. So here's the code I have so far:
#include <iostream>
#include <fstream>
#include <stdlib.h>
#include <string>
using namespace std;
const int MAX_STUDENTS=100;
const int MAX_COURSES=25;
const int NAME_SIZE=30;
const int COURSE_COLUMNS=4;
const int GRADE_ROWS=10;
//Entity Classes
class Course
{
//Two private member variables
private:
string courseText;
int courseID;
public:
//Constructor
Course(void)
{
//Just providing initial value to the two object variables
courseText;
courseID=-1;
}
//Setters and Getters for each variable
string getCourseText(){
return courseText;}
void setCourseText(string userEnteredText){
courseText = userEnteredText;}
int getCourseID(){
return courseID;}
void setCourseID(int userEnteredID){
courseID = userEnteredID;}
};
class Student
{
//Private member variables
private:
string studentText;
int studentID;
int** coursesAndGrades;
int enrolledCoursesCount;
int timesReallocatedColumns;
int timesReallocatedRows;
public:
//Constructor
Student(void)
{
//Just providing initial value to the object variables
studentText;
studentID=-1;
coursesAndGrades = new int*[GRADE_ROWS+1];
for(int i=0;i<(GRADE_ROWS+1);i++)
{
coursesAndGrades[i] = new int[COURSE_COLUMNS];
}
enrolledCoursesCount=0;
timesReallocatedColumns=0;
timesReallocatedRows=0;
}
//Setters and Getters for each variable
string getStudentText(){
return studentText;}
void setStudentText(string userEnteredText){
studentText = userEnteredText;}
int getStudentID(){
return studentID;}
void setCourseID(int userEnteredID){
studentID = userEnteredID;}
int getCoursesAndGrades(int gradeRow, int courseColumn){
return coursesAndGrades[gradeRow][courseColumn];}
void setCoursesAndGrades(int gradeRow, int courseColumn, int entry){
coursesAndGrades[gradeRow][courseColumn]=entry;}
int getEnrolledCoursesCount(){
return enrolledCoursesCount;}
void setEnrolledCoursesCount(int enrolledCount){
enrolledCoursesCount = enrolledCount;}
int getTimesReallocatedColumns(){
return timesReallocatedColumns;}
void setTimesReallocatedColumns(int reallocColumnCount){
timesReallocatedColumns = reallocColumnCount;}
int getTimesReallocatedRows(){
return timesReallocatedRows;}
void setTimesReallocatedRows(int reallocRowCount){
timesReallocatedRows = reallocRowCount;}
};
Now, I've got a container class called GradeBook which contains dynamically allocated arrays of these two entity class objects.
class GradeBook
{
private:
Course* courses;
Student* students;
public:
//Constructor
GradeBook(void)
{
courses = new Course [MAX_COURSES];
students = new Student [MAX_STUDENTS];
}
}
I'm trying to figure out the proper way to translate the setter and getter functions from my entity classes to the container class so I can change individual elements of each class object in the dynamically allocated array. These changes will happen in more public member functions in the container class, but I'm completely stumped. I hope this question makes sense, and I'm not looking for anyone to write all of the setters and getters for me, I just need someone to point me in the proper direction for the syntax. Thanks everyone who made it through this!
If you will have something like this:
class GradeBook
{
public:
...
Student& student(int idx) { /*some boundary check here*/
return students[idx]; }
}
then you can use that method as:
GradeBook theBook;
...
auto idOfFirstStudent = theBook.student(0).getStudentID();
You just need to decide what that student() method shall return: it can return reference (as above) or pointer to student (instance). In later case you can return nullptr in case of out-of-bound errors. In first case the only reasonable option is to throw an error.
So there's no magic needed here, but you do need to decide how you want to do it. One way would be to just write something like:
void GradeBook::setCourseText(int i, const string &txt) {
courses[i].setCourseText(txt);
}
BTW, I would highly recommend using std::vector and at() rather than new.