I am new to C++, and was wondering what I am doing wrong.
I am trying to create a text-based adventure game that keeps track of player stats using an add or remove function. Currently, my function does not add five points to trust and I am trying to get it to.
#include "function.h"
using namespace std;
int main() {
double trust=100;
editPlayer user(100);
//asks user choice
cin >> firstChoice;
if (firstChoice == 1) {
user.addTrust(trust);
cout << trust;
Here is my function.cpp only using trust as an example:
#include "function.h"
editPlayer::editPlayer(double trust) {
}
void editPlayer::addTrust(double trust){
trust +=5;
}
void editPlayer::removeTrust(double trust){
trust -=5;
}
And here is my function.h:
#include<iostream>
#include<string>
using namespace std;
class editPlayer{
public:
editPlayer(double trust);
void addTrust(double);
void removeTrust(double);
};
Lets take your addTrust function:
void editPlayer::addTrust(double trust) {
trust += 5;
}
This will modify the local variable trust, and then the function will end. When the function ends, the life-time of the local variable trust also ends, and the modifications you made to it will be lost.
If you truly want to modify the argument, you need to either pass it by reference:
void editPlayer::addTrust(double& trust) {
trust += 5;
}
Or return the new value:
double editPlayer::addTrust(double trust) {
return trust + 5;
}
If you return the new value, you need to assign to it when calling the function:
trust = user.addTrust(trust);
With the above said, the code and the editPlayer class doesn't make much sense. There's just no need for a class editUser really. Possibly addTrust could be a non-member function, or maybe not a function at all.
The class name doesn't make sense, since it doesn't "edit" anything. And passing an argument to the constructor also doesn't make sense since the objects doesn't have any internal state (the value passed to the constructor is just discarded).
Currently you're not storing anything specific on behalf of user object (an object of the editPlayer class.
The cout << trust; statement just prints a value of the trust local variable which you declared at the beginning: double trust=100;. Because this variable hasn't been changed anyhow since that initialization it is still equal to 100 and this is what you see.
In order to track any editPlayer-specific information the best idea is to store that information as a data member of the class editPlayer. You can declare a data member representing the trust of an object like this:
class editPlayer{
public:
editPlayer(double trust);
void addTrust(double);
void removeTrust(double);
double getTrust() const; // add also this one, will be useful
private:
double m_trust {0}; // <---- here - a data member, aka. a class field
};
Now you must refine you constructor to let it utilize the parameter which it takes and assign its value to this new data member (because currently the constructor does nothing):
editPlayer::editPlayer(double trust) {
m_trust = trust;
}
Now in the member functions that you already have just rename the variable so that it reflects the trust data member (and not the parameter) which effectively will allow to update its value:
void editPlayer::addTrust(double trust) {
m_trust += 5;
}
void editPlayer::removeTrust(double trust) {
m_trust -= 5;
}
double editPlayer::getTrust() const { // add definition of our "getter"
return m_trust;
}
Finally you can replace that cout << trust; which we already discussed (still prints the local variable's value) with an invokation of the getter which yields m_trust's value:
cout << user.getTrust();
and see the actual effect of performing the addTrust() operation as well as get delighted with your legitimate object-oriented program.
In general the code you are asking can be covered by classes, member declarations and also a pinch of object oriented programming.
The internet has lots of good (and less than good) tutorials if you search for it.
I would try my luck with some of the following searches
CPP + classes
CPP + member declarations
CPP + dynamic vs. static memory allocation (pointers and stuff)
object oriented programming (OOP)
The examples on this site provide good (and short :D) examples of alot of basic concepts imho.
https://www.tutorialspoint.com/cplusplus/cpp_classes_objects.htm
Some of the topics also apply to other languages.
The first block with my comments:
#include "function.h"
using namespace std; // dont get into the habbit of using namespace std;
// the above can potentially open up for bugs
int main()
{
double trust=100; // This variable is declared in this scope({ ... })
// and will get deallocated once the scope ends with the character '}'
editPlayer user(100); // instance of editPlayer named 'user' is constructed
//asks user choice
cin >> firstChoice;
if (firstChoice == 1) {
user.addTrust(trust); // calling function on user object
cout << trust;
}
Now looking at the .h file i would advocate against including headers that you dont use in the header.
For small projects it does not matter at all - but for big projects of thousands lines of code removing unused includes can speed up things.
Some would prefer forward declarations - which you can look into once you are more comfortable with the basics of cpp.
#include<iostream> // not used here
#include<string> // not used
using namespace std; // disaster waiting to happen
class editPlayer{
public:
editPlayer(double trust);
void addTrust(double);
void removeTrust(double);
};
The .cpp file
#include "function.h"
editPlayer::editPlayer(double trust) {}
// function implementation with argument - but argument is not used - change to void fun(double) -> fun(void) OR fun()
void editPlayer::addTrust(double trust) { trust +=5; }
void editPlayer::removeTrust(double trust) { trust -=5; }
I did an example with class declaration and member variables.
#include <iostream>
#include <string>
// this is a class declaration
class Player
{
protected: // protected member variables
double _trust;
public: // public interface
Player(double trust);
void addTrust(double);
void removeTrust(double);
double getTrust() const;
};
// Implementation of public interface
// notice _trust is the member defined in the class
Player::Player(double trust) : _trust(trust) {} // constructor
// example of default parameters (do note that only definition or declaration can have them)
// This means that calling the function without arguments will become 5
void Player::addTrust(double trust = 5) { _trust += trust; }
void Player::removeTrust(double trust = 5) { _trust -= trust; }
double Player::getTrust() const {return _trust; }
int main()
{
Player player(100); // this will invoke the constructor - and the player object will get initialised with the given state
std::cout << player.getTrust() << std::endl;
// variable to buffer input data into - assuming type int wrt. following if
int firstChoice;
//asks user choice
std::cin >> firstChoice;
if (firstChoice == 1)
{
player.addTrust(25);
player.addTrust();
}
std::cout << player.getTrust();
}
Happy coding !
Related
Say I have a header file:
class.h
#pragma once
#include <iostream>
#include <string>
using namespace std;
class my_class
{
private:
string var1;
public:
my_class(string var1_val) { var1 = var1_val; };
};
I wish to declare a my_class variable as a global so it can be used across functions. However, it cannot be initialised outside the main function, as it requires user input to initialise. This poses a problem, as if the below code is run, I get: 'my_class': no appropriate default constructor available
source.cpp
#include <iostream>
#include <string>
#include "classes.h"
using namespace std;
my_class f;
int main(){
string inpt;
cout << "Enter var1 value: ";
cin >> inpt;
f = my_class(inpt);
}
How would I define the variable f so I could initialise it in main, but also use it in another function in the source.cpp file?
There are a few things mixed in the question. I'll try to address them individually.
The error message about the default constructor is exactly that: you are asking to instantiate an instance of that class but you only provide one way of doing so: the constructor with a string parameter.
Two ways you can deal with that "directly":
provide a default constructor, by either having it explicitly or making the string parameter optional, like my_class(string var1_val = {})
provide the said parameter at a time of instantiation: my_class f{""};
Have a variable "outside" in the global scope but initialized in main()... Also, a few ways to deal with that (personally I would advise against such a practice for various reasons, but providing options here for completeness):
Use pointers. Declare your variable as my_class * f{nullptr}; or, even better, as a smart pointer: std::unique_ptr<my_class> f; and instantiate the object in your main as either a naked pointer f = new my_class("string"); or a smart pointer f = std::make_unique<my_class>("args");
have that variable local to main() and pass it into whatever function you need it in
You might also look into using a Singleton Pattern where you have a factory function that manages your f (again, a horrible idea in this case, but providing it for completeness):
my_class & get_my_class(string s = {}){
static my_class * mc{nullptr};
if(!mc){ mc = new my_class{s}; } // <-- memory leak here unless you use unique_ptr
return *mc;
}
int main(){
// ...
auto & m{get_my_class("user input")};
// ...
}
void other_function(){
auto & f{get_my_class()};
// use f
}
The problem that you describe
as if the below code is run, I get: 'my_class': no appropriate default constructor available
is because you have declare another constructor with some parameter. In this case, compiler will not generate default constructor. You have to do it by yourself. so the class should look like:
class my_class
{
private:
string var1;
public:
my_class(){};
explicit my_class(string var1_val) :
var1(var1_val)
{};
};
Good practice is when you are making constructor with one argument mark it as explicit. Another good practice is to assign variables in constructor initialization list.
Best Regards
Just do this
my_class(string var1_val="") { var1 = var1_val; };
Provide default argument & you are good to go.
Just to get the compiler to shut up.
Although using global object is not a good solution.
That is not directly possible... a global class instance requires initialization (only types like int or double can be left initialized, but only in local scopes - as global they're always initialized - and this possibility of leaving variables uninitialized is also something many think is a design error of the C++ language - most younger languages do not provide this option as experience taught us that it's a source of nasty bugs and provides no real advantage).
What you want to do could be interpreted as a variation on what is normally called the "singleton pattern" ... i.e. providing all the modules access to a single instance of a class.
This in C++ is normally done using a function that returns a reference to the variable... for example:
------------------------------------------------------------ parms.h
...
struct Parms {
std::string user_name;
int user_age;
static Parms& get(); // Providing access to the singleton
};
-------------------------------------------------------- module1.cpp
#include "parms.h"
...
void foo() {
// access the singleton
std::cout << "Hello " << Parms::get().user_name << "\n";
}
---------------------------------------------------------- parms.cpp
#include "parms.h"
...
static Parms* parmsp;
void init_parms(const std::string& user_name, int user_age) {
// creates the singleton
parmsp = new Parms{user_name, user_age};
}
Parms& Parms::get() {
// Provide access to the singleton
if (!parmsp) {
throw std::runtime_error("Parameters not yet initialized");
}
return *parmsp;
}
So I'm an newbie to programming and I have encountered a
case for which I suppose qualifies as an authentic question
in this awesome forum. Is there a way to write statements inside my get functions so that I can obtain all the changed data member values without having to create multiple get functions
for each data member?
Regards
I am practicing building programs which are easy to maintain by localizing the effects to a class's data members by accessing and manipulating the data members through their get and set functions. In this regard I have two data members for which I wish to change. After compiling, the set functions works well by changing the values but the get functions can only return one of the data member values at a time.
class GradeBook
{
public:
void setCourseName(string code,string name)
{
CourseCode = code;
CourseName = name;
}
string getCourseName()
{
return CourseCode;
return CourseName;
}
void displayMessage()
{
cout<<"Welcome to the GradeBook for: \n" <<getCourseName()
<<endl;
}
private:
string CourseName;
string CourseCode;
};//end class GradeBook
After compiling and running the program, the program outputs the CourseCode but the CourseName doesn't get displayed. I had to create two get functions each to obtain the two data members. I don't want to have 2 get functions to obtain the data member values. I just want to use one get function to keep the code at minimum.I wish to use one get function to return two values for each data member. I have already tried using one return statement and separated the data members with a comma.
Your idea of using return twice cannot work, the first return will return control to the caller and the second will never be executed. You should have got warning about it from your compiler.
I believe that an initial solution could be to use std::pair (docs: https://en.cppreference.com/w/cpp/utility/pair), see snippet below.
NOTE: using namespace std; (which is most likely what you are doing in the code you do not show), is a bad practice, consider using the fully qualified name
#include <string>
#include <utility>
#include <iostream>
//Bad practice, I added it only to keep differences with OP code small
using namespace std;
class GradeBook
{
public:
void setCourseName(string code,string name)
{
CourseCode = code;
CourseName = name;
}
std::pair<string, string> getCourseName()
{
return {CourseCode, CourseName};
}
void displayMessage()
{
//only in C++17
auto [code, name] = getCourseName();
cout<<"Welcome to the GradeBook for: \n" << code << " - " << name
<<endl;
}
private:
string CourseName;
string CourseCode;
};//end class GradeBook
Note that auto [code, name] is a feature called structured binding, available only in C++17, if you have an older compiler, you have to return a std::pair<std::string, std::string> and access its elements using the member variables first and second.
Now, std::pair is good for this contrived example, but, for your case, you might want to consider doing something a bit more readable, because the elements of the pair have the same type so the user of your library will have difficulties remembering what is the first and second element. So you might want to use a custom-made struct with some more meaningful names.
#include <string>
#include <utility>
#include <iostream>
//Bad practice, I added it only to keep differences with OP code small
using namespace std;
struct CourseCodeAndName{
std::string code;
std::string name;
};
class GradeBook
{
public:
void setCourseName(string code,string name)
{
CourseCode = code;
CourseName = name;
}
CourseCodeAndName getCourseName()
{
return {CourseCode, CourseName};
}
void displayMessage()
{
auto codeAndName = getCourseName();
cout<<"Welcome to the GradeBook for: \n" << codeAndName.code << " - " << codeAndName.name
<<endl;
}
private:
string CourseName;
string CourseCode;
};//end class GradeBook
See this example. Alternatively you can use std::tuple.
class GradeBook
{
/* ... */
public:
std::pair<std::string, std::string> get(){
return std::make_pair(CourseName, CourseCode);
}
};
int main()
{
GradeBook book1("Hello","World")
auto result = book1.get();
cout << result.first << result.second;
}
If you write:
return x,y;
or:
return x;
return y;
You should know that in first case you get the last value (you get y), and in second case you get the value of first return (you get x, because as soon as compiler see return, function will return the value, and then function will go in epilogue state (cleaning of stack memory assigned to function, both inline and non-inline function).
And about the use of get function it's normal. If you want to use the value to do something of logic (not to display), yes you should use a lot of get function. Instead if you want to display the values, use a void function, for example "void printData();", and inside it write code to print data. You probably setted the class variables as private (following the encapsulation rules) so you will have access to them inside the print function.
So i have made this task system, or i'm trying to make it, so that if someone has done more than seven tasks, the next person has to do seven.
the doubles (Bodine, Finn, Tycho) are the persons. Now i dont know if i used it correctly,(if they need to be doubles) and how i use them in this line of code:
if (taskNumbers == 7)
{
std::cout << "It's " + /*what to do here? */ + "time!";
what i want is that if the task numbers are higher than seven, and Bodine has done 7 tasks, it says "Its finn his time!"
#include <iostream>
using namespace std;
double Bodine;
double Finn;
double Tycho;
bool tasksDone = true;
int taskNumbers = 0;
int main()
{
if (taskNumbers > 7)
{
std::cout << "It's " + /*what to do here? */ + "time!";
return 1;
}
}
This is one of my first projects yet(im 13, so yeah....). I only need to know how to use the next variable!
Well, you're not really keeping track of whose turn it is. Also, double is not the right tool for the job here. I would do something like this:
std::vector<std::string> users = { "Bodine", "Finn", "Tycho" };
int currentUser = 0;
Now we have a list of names as well as a counter that says whose turn it is. 0 is for the first person, 1 for the second person, and 2 for the third person. Then we need the logic to advance that counter:
void advanceUser() {
if (++currentUser >= users.size()) {
currentUser = 0;
}
}
This increases currentUser, and when it is bigger than the amount of people, it loops back to 0, so the people take turns correctly.
Next about the task logic, I would suggest something like this:
int tasksDone = 0;
void incrementTasksDone() {
if (++tasksDone >= 7) {
advanceUser();
std::cout << "It's " + users[currentUser] +"'s time!" << std::endl;
tasksDone = 0;
}
}
Here we have a counter that keeps track of the amount of tasks, and when it hits 7, it sets it back to 0 and announces that it's the next user's turn after callling advanceUser to set that right.
You can then call incrementTasksDone however you want, for instance I tested it like this:
int main()
{
for (int i = 0; i < 100; i++) {
incrementTasksDone();
}
}
That would get 100 tasks done, for instance, so the turns would change 14 times in the process and it would print the message every time.
Also, to get this example to run, be sure to add the following includes:
#include <vector>
#include <string>
#include <iostream>
Hello and welcome to C++. Many will say that C++ is a bad language of choice for starters. Well I started with C++ myself a long time ago and I'm still learning to this day. I am 100% self taught and I didn't have the advantages that people do today with the amount of information that is available over the internet as well as the modern formats that are available. When I first started learning C++, the internet was in the stage of booming; but most websites back then were nearly pure text and even simple pictures or graphics took a while to load to the screen because this was in the era of Dial Up. Today, people who are starting out have the advantages of both this website, other similar sites and even youtube videos. However, I still enjoy helping where I can because it doesn't only help you, but it also helps me to improve what I have already learned. C++ has evolved over the years so what I'll do here is demonstrate to you a small application that I believe mimics the behavior of what you have described you are trying to do. Some of these techniques are a little advanced especially for beginners, however I think it is a good fit that someone who is new learns these concepts early.
Storage Types & Lifetime - There are basically 4 main storage types in C++: Automatic, Dynamic, Static and Thread. I mostly focus on the first 3.
Automatic: It has the lifetime of the scope that it is declared in and will automatically be destroyed once that scope exits from its closing brace }
Dynamic: Memory that is represented by pointers but declared with new and must have a matching delete, or arrays new[] and delete[] respectively. They can live longer than the scope they are declared in. They will live until their matching delete is called. If no matching delete takes place, this leads to a memory leak, invalid pointers, dangling pointers & references and undefined behavior. Special Care needs to be taken when using raw-pointers; it's advisable to use either containers or smart pointers.
Static: These are typically found in the global namespace and or global filespace. If a static is declared in the main.cpp it will have a lifetime of the application and the scope of the whole program. If they are declared in other cpp files, they will have the scope of that file, unless if they are declared in some header file, then they will have the scope of what other translation unit includes that header. They are similar to Automatic in the sense they will automatically be destroyed, but they differ as in the fact that they are initialized only once, the maintain their state and you can only have a single instance of them.
For a demonstration of the different types of storage classifications you can see my previous answer to this Q/A.
Classes and Inheritance: - (I will not involve Polymorphism).
Classes:
Classes and Structs are user defined data types.
The difference between the two is the default access
By default: Structs have Public Members & Classes have Private Members
Members of a Class or Struct can be any built in type, pointers to types, another user defined data type, and methods or functions.
Member Variables can be of any Storage Type: Automatic, Dynamic, Static and Thread, however, member functions are usually Automatic but can be Static. If you have a member variable it has to be initialized outside of the Class's Declaration to resolve it's symbols.
They have Constructors and Destructors by default, but one can create their own custom Constructor or Destructor. You will typically see people mention them by their short names: ctor & dtor respectively.
One class can inherit from another.
Inheritance:
You have Base or Super Classes, and you have Derived or Child Classes
When Inheriting from a Base class, if the Base class's ctor is Public, this means you can create an object of both the Base & Derived Classes. Sometimes you want this kind of design, but there are times when you don't.
If you do not want the user to be able to create an instance of the Base Class, but are able to create an instance of the Derived Class then all you need to do is make sure that 1st its ctor is Protected. If you declare it Private, then even your Derived Classes can not access it and therefore they can not be declared. *2nd You want to make sure that your Destructors - dtors are Virtual; otherwise you will have issues with the order in which classes are destroyed.
A Base Class can have Member Functions that are Virtual which means All Derived Classes must Implement that Function.
A Base Class can have Member Functions that are Purely Virtual which is similar above, but also prevents anyone from declaring an instance of this Base Class because this makes the Base Class Abstract which means it's an idea for an interface.
Example Virtual Function: virtual update();
Example Purely Virtual : `virtual update() = 0;
Containers - (I will use a std::container, but I won't involve any Algorithms)
There are many kinds of containers for different needs; these containers help to keep your program simple, easy to manage and debug, user friendly and to prevent many future headaches instead of using basic C Arrays.
There are a few different types and they each have their own purpose and properties which I will not go over all of their details as you can find a plethora of information on the net regarding them, but I will label and group them to their similar properties: The groupings are Sequence Containers, Associative Containers, & Unordered Containers and these all belong to the std:: namespace. The major difference between the groupings are: Sequence Containers are like arrays and linked lists, Associative Containers are binary trees, and Unordered Containers are similar to the binary trees except they are not in order, they are considered hash tables.
Sequence: vector, dequeue, queue, list, forward_list, array
Associative: set, multiset, map, multimap
Unordered: unordered_set, unordered_multiset, unordered_map, unordered_multimap`
What makes these containers powerful is the ability to either traverse them quickly or to insert and find quickly depending on which container you are using. Another good feature is helping in the process of memory management. Finally is the numerous algorithms and iterators that can do work on them.
For more information on the stl I advise to watch this youtube series by Bo Qian
Smart Pointers There are a few different types, but the most important two are std::shared_ptr<T> and std::unique_ptr<T>. The major difference between the two is that shared has a reference count to how many objects have access to it; it means it has a public type interface and can use copy semantics; unique on the other hand has only 1 owner at a time, it can transfer ownership but once it does the original owner no longer has access to it. You can not copy unique, but you can move them. These smart pointers help with the use of dynamic memory and life time object management to prevent memory leaks, invalid pointers, dangling pointers and references, undefined behavior etc. They help to minimize the use of new & delete and new[] & delete[] respectively.
Now that you have an understanding of some of the concepts that you will see quite often in C++ programs; I will now show you the simple application that I have written based off of what it was that I perceived you were trying to do:
#include <array>
#include <exception>
#include <memory>
#include <string>
#include <iostream>
class Person {
protected:
std::string name_;
int tasksCompleted_;
public:
const std::string& whoIs() const { return name_; }
int numberTasksCompleted() const { return tasksCompleted_; }
virtual void performTask() = 0;
protected:
explicit Person(const std::string& name) : name_{ std::move(name) } {}
virtual ~Person() = default;
};
class Bodine final : public Person {
private:
static int currentTask;
public:
explicit Bodine(const std::string& name = std::string("Bodine")) : Person(name) {}
virtual ~Bodine() = default;
virtual void performTask() { currentTask++; tasksCompleted_ = currentTask; }
};
int Bodine::currentTask = 0;
class Finn final : public Person {
private:
static int currentTask;
public:
explicit Finn(const std::string& name = std::string("Finn")) : Person(name) {}
virtual ~Finn() = default;
virtual void performTask() { currentTask++; tasksCompleted_ = currentTask; }
};
int Finn::currentTask = 0;
class Tycho final : public Person {
private:
static int currentTask;
public:
explicit Tycho(const std::string& name = std::string("Tycho")) : Person(name) {}
virtual ~Tycho() = default;
virtual void performTask() { currentTask++; tasksCompleted_ = currentTask; }
};
int Tycho::currentTask = 0;
int main() {
try {
std::array<std::shared_ptr<Person>, 3> people{
std::shared_ptr<Person>(new Bodine()),
std::shared_ptr<Person>(new Finn()),
std::shared_ptr<Person>(new Tycho())
};
// For each person in array
const int MAX_TASKS = 7;
int currentPerson = 0;
for (auto& p : people) {
std::cout << p->whoIs() << " has performed task #:\n";
while (p->numberTasksCompleted() < 7) {
p->performTask();
std::cout << p->numberTasksCompleted() << '\n';
if (p->numberTasksCompleted() == MAX_TASKS) {
currentPerson++;
if (currentPerson <= (people.size() - 1) ) {
std::cout << "It's your turn " << people[currentPerson]->whoIs() << " to do some tasks.\n";
}
break;
}
}
}
} catch( std::runtime_error& e ) {
std::cerr << e.what() << std::endl;
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
-Output-
Bodine has performed task #:
1
2
3
4
5
6
7
Finn has performed task #:
1
2
3
4
5
6
7
Tycho has performed task #:
1
2
3
4
5
6
7
Link to above program.
I know this is quite a bit to read; but please look closely over the application to try and see what it is doing. You can copy and paste this right into your own IDE and try to build and run it to see it in action. Hopefully this will give you a grasp of what C++ is.
-Edit-
About the code above: it is a little more complex than what it truly needs to be. First off you would not really see a single person's identity as it's own class. I only did this to demonstrate what inheritance is. I choose to use std::array instead of std::vector mainly due to the fact that you had 3 specific people from your proposal. If you have an unknown amount of people at compile time then std::vector would be the correct container to use. You wouldn't really need to use inheritance either. Also if you look at the 3 derived classes there is a lot of duplicate code. I also used shared_ptrs to show how they can be used, but are not necessary in your specific situation. I also used static member variables in the Derived Classes to show static storage.
Here is a simplified version of the above code to mimic your behavior. Both programs do the same task similarly, the only major differences are: The use of inheritance with purely virtual methods, static member storage, container type, and dynamic memory via the use of shared_ptr.
#include <exception>
#include <iostream>
#include <string>
#include <vector>
class Person {
private:
std::string name_;
int tasksCompleted_;
public:
explicit Person(const std::string& name) : name_(name), tasksCompleted_(0) {}
const std::string& whoIs() const { return name_; }
int numberTasksCompleted() const { return tasksCompleted_; }
void performTask() { tasksCompleted_++; }
};
int main() {
try {
std::vector<Person> people{
Person( "Bodine" ),
Person( "Finn" ),
Person( "Tycho" )
};
// For each person in array
const int MAX_TASKS = 7; // Don't like magic numbers!
int currentPerson = 0; // Needed variable
for (auto& p : people) {
std::cout << p.whoIs() << " has performed task #:\n";
while (p.numberTasksCompleted() < MAX_TASKS) {
p.performTask();
std::cout << p.numberTasksCompleted() << '\n';
if (p.numberTasksCompleted() == MAX_TASKS) {
currentPerson++;
if (currentPerson <= (people.size() - 1) ) {
std::cout << "It's your turn " << people[currentPerson].whoIs() << " to do some tasks.\n";
}
break;
}
}
}
} catch( std::runtime_error& e ) {
std::cerr << e.what() << std::endl;
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
Here is the link for this version of the program!
I have an object with a method that needs to mutate an outside instantiated object. I've been trying to reference the object in the parameter and that is clearly not working. This is what I have:
#include <iostream>
#include <cstdlib>
#include "Character.h"
using namespace std;
class TesterClass {
public:
void printStuff();
TesterClass(Character& userChar);
private:
Character& character;
};
TesterClass::TesterClass(Character& userChar)
{
character = userChar;
}
int main() {
Character userCharacter;
TesterClass tester(userCharacter);
return 0;
}
My question is how to can I use the instantiated tester class to edit the Character object via parameter passing. I'm very new at C++ and I've read every perceivable definition of reference and point passing, and it just doesn't seem to want to click.
Your constructor should be:
TesterClass::TesterClass(Character& userChar):character(userChar){}
Also see this question.
To address the comment, here's example code where the value is modified:
#include <iostream>
#include <cstdlib>
typedef char Character;
using namespace std;
class TesterClass {
public:
void printStuff();
TesterClass(Character& userChar);
private:
Character& character;
};
TesterClass::TesterClass(Character& userChar):character(userChar)
{
}
void TesterClass::printStuff() {
cout << character << endl;
cout << ++character << endl;
}
int main() {
Character userCharacter = 'a';
TesterClass tester(userCharacter);
tester.printStuff();
cout << userCharacter << endl;
++userCharacter;
cout << userCharacter << endl;
tester.printStuff();
return 0;
}
The output is
a
b
b
c
c
d
I agree with the previous answer/comments - You really should use an initialization list in your constructor. The thing is that your data-members are initialized through the initialization list (this happens BEFORE the body of the constructor is called). In your case, you have a Character& as a member. Since this is a reference, it HAS to be assigned something. I'm not sure which compiler you're using, but AFAIK that code shouldn't even compile.
What you're probably looking for is passing the reference in your main-method, like:
int main()
{
Character userCharacter;
// Notice the use of the &-operator
TesterClass tester(&userCharacter);
return 0;
}
At this point, you're no longer talking about a Character-instance, but of the memory address of the instance. So, since you're passing the mem-address, it's actually a pointer you need in your class, not a reference. (For instance, userCharacter.SomeMethod() is synonymous to (&userCharacter)->SomeMethod() where & references and -> dereferences).
Instead, you could write your TesterClass as:
class TesterClass
{
public:
void printStuff();
TesterClass(Character* userChar);
private:
Character* character;
};
TesterClass::TesterClass(Character* userChar)
: character(userChar) // <- Notice the init-list
{}
That way, in your TesterClass instance, you'll have a pointer that points to the same memory address where the userChar-instance resides.
As a sidenote: It can be good to notice though that userCharacter is a local variable, which means that it'll be destroyed when it runs out of scope. In this case it's not really a problem since tester is local as well. But if you're not used to working with pointers - Just a word of caution. Make sure you never pass the pointer (since you're storing the address in a class member) to a TesterClass-object that lives beyond the scope of the variable whose reference you're passing. That'll leave you with a dangling pointer.
I hope that helps you :)
I can't figure out why I get this error: "the function was not declared". I am still a newbie at programming, but I am trying my best to learn it!
so here is my code, I would be realy greatful if you could help me:
main:
#include <iostream>
#include <vector>
#include "szovegkezelo.h"
using namespace std;
int main()
{
string sz;
beolvas(sz);
kiir(sz);
return 0;
}
header:
#ifndef SZOVEGKEZELO_H_INCLUDED
#define SZOVEGKEZELO_H_INCLUDED
#include <iostream>
using namespace std;
class szovegkezelo {
protected:
string sz;
public:szovegkezelo
void beolvas(string &sz);
void kiir(string t);
};
#endif // SZOVEGKEZELO_H_INCLUDED
cpp:
#include "szovegkezelo.h"
#include <iostream>
void szovegkezelo::beolvas(string &sz)
{
getline(cin, sz);
}
void szovegkezelo::kiir(string t)
{
cout << "a beadott szoveg: " << t << endl;
cout << "a string hossza: " << t.size() << endl;
}
From what it looks like, you are trying to call a classes function (method) called 'beolvas' from 'main' but because it belongs to a class, you can't call it like that, you need to create an instance of that class and call the method on that instance, or make the function static and call it from the class.
Your first option is to create an instance of the class and then call the methods on the class like so:
int main()
{
string sz;
szovegkezelo szov;
szov.beolvas(sz);
svoz.kiir(sz);
return 0;
}
Your second option is to make the functions in your class static, this way they will not need an instance of the class to be called:
int main()
{
string sz;
szov::beolvas(sz);
svoz::kiir(sz);
return 0;
}
static void szovegkezelo::beolvas(string &sz)
{
getline(cin, sz);
}
static void szovegkezelo::kiir(string t)
{
cout << "a beadott szoveg: " << t << endl;
cout << "a string hossza: " << t.size() << endl;
}
Been a while since I've done anything static in c++ so please correct me if I've done something wrong in the second option.
Your two or more data types... error comes from a misuse of...something...after that public access specifier.
Change this:
public:szovegkezelo
to this:
public:
If you're trying to make a constructor, it needs to be declared like any other function, minus the return type.
Your other error occurs because this function was declared improperly.
Other than that, you need to create an object before you can call the class's functions. Each object has it's own set of variables that the functions work on. I would seriously recommend reading a good beginner C++ OOP book.
Somewhere in main, you need to create an object:
szovegkezelo myObject;
Then, use it to call functions:
myObject.kiir (sz);
Finally, note that your data members should typically be declared with the private access specifier. protected has nothing to do with normal classes that are not inherited from.
couple of things :
1) In main you have not instantiated an object of szovegkezelo and you are trying to call beolvas . Compiler is looking for a free function beolvas whereas you have declared beolvas as member function
2) public:szovegkezelo is not right if you are looking for a default constrcutor that does nothing don't have that line else if you need to do something specific with default construct declare it as szovegkezelo() in header.
3) as mentioned in comments it is not a good practice to put
using namespace std in header files or any using namespace