Assign value of variable in class C++ - c++

Hello I can't find out how to assign values to my variables that I am using in one of my class. I am getting error nonstatic member reference must be relative to a specific object so I am doing something wrong but I cant figure how o make it right.
class Triedenie_cisla{
public:
Triedenie_cisla(int *poleHodnot, int ddlzka);
int *pole, dlzka;
double bubble_time, selection_time, insert_time, quick_time;
vector<int> mnozina_int;
string vypis_pola();
void BubbleSort_int();
void SelectionSort_int();
void InsertSort_int();
void QuickSort_int();
};
Then in functions that make sorts, I measure the time and trying to assign the time to variables like that
Triedenie_cisla::insert_time = dif;
What I am doing wrong ? Thanks

You need to find a good book on C++, those are basic things.
nonstatic member reference must be relative to a specific object
means that to modify insert_time you must do it on existing object of class: Triedenie_cisla
Then in functions that make sorts, I measure the time and trying to assign the time to variables like that Triedenie_cisla::insert_time = dif;
you should do it like that:
void Triedenie_cisla::BubbleSort_int() {
// ....
insert_time = dif;
//
}

You have to create an object of your class. Then, assigning values is possible.
Triedenie_cisla obj;
obj.insert_time = dif;
Otherwise, the compiler assumes that you want to change the value of a static variable, ie.
a variable that exists once for the whole class. To do so, you would have to state
that insert_time is a static variable.
For example:
static double insert_time;

If I understand it well, you wish to set the value of insert_time inside your own sorting function which are already part of the class Triedenie_cisla.
Therefore you just need to do
this->insert_time = dif;
or even
insert_time = dif;
would be enough

You can not call a variable/method only using class name unless it is static variable/method of the class. Therefore, solution of your problem is:
Solution-1
First make a object of your class:
Triedenie_cisla object_1 = new Triedenie_cisla() ;
Call the variable using object name.
object_1.insert_time = dif;
Solution-2
You can solve this problem also using static key word in front of insert_time in the class declaration:
static double bubble_time, selection_time, insert_time, quick_time;

Related

Cannot assign to non-static data member within const member function

I am attempting to use std::unordered_set as a hash table to store many CreditCard's. CreditCard and another class CardDatabase are defined as follows:
class CreditCard {
private:
string cardHolder;
unsigned long long cardNumber;
int limit;
int balance;
public:
CreditCard(string in_cardHolder, string in_cardNumber, int in_limit) {
cardHolder = in_cardHolder;
cardNumber = stoll(in_cardNumber);
limit = in_limit;
balance = 0;
}
void ChangeBalance(int amount) const {
balance += amount; // SECOND ERROR
}
};
class CardDatabase {
private:
unordered_set<CreditCard> cards;
unordered_set<CreditCard>::iterator iter;
public:
CardDatabase() { }
void AddCard(cardHolder, cardNumber, int limit) {
CreditCard tempCard = CreditCard(cardHolder, cardNumber, limit);
cards.insert(tempCard);
}
void Charge(string cardHolder, int chargeAmount) {
iter = cards.find(cardHolder);
iter->ChangeBalance(chargeAmount); // FIRST ERROR
}
}
Initially I was getting the following compile error at FIRST ERROR: Member function 'ChangeBalance' not viable: 'this' argument has type 'const CreditCard', but function is not marked const. So, I added the "const" to the ChangeBalance function. However, after doing that I get the following compile error at SECOND ERROR: Cannot assign to non-static member within const member function 'ChangeBalance'.
Is there any way to fix this error without changing balance to a static variable? It is obviously important that the balance be different for each CreditCard instance.
Any help is appreciated.
EDIT:
Thank you all for your quick answers. I feel I should clarify something. I already added the proper hash functionality elsewhere in my code:
namespace std {
template <>
struct hash<CreditCard> {
size_t operator()(const CreditCard& cc) const
{
return hash<string>()(cc.GetCardHolder());
}
}
}
Also, the code I posted initially pasted is from a much larger code base and I didn't delete all the necessary namespacing stuff at first before posting the question. My apologies for the confusion.
Members of an unordered_set are constant, and cannot be changed once they're in the unordered_set, by default. You are trying to change the objects in the set, and the compiler is properly telling you that you can't do this.
The only possible way to do this correctly (explained only for educational purposes, because this is bad class design):
Explicitly declare the individual fields that can be modified in this manner as mutable.
Use a custom hash function with your unordered_set, and the hash function must exclude the value of mutable fields from the value of the calculated hash.
Otherwise, modifying the contents of the object in the set obviously changes its hash value, which will result in undefined behavior.
Again, this is explained for informational purposes only. This is not a good class design.
The clean way to do this would be to assign a unique identifier to each CreditCard (you know, like a credit card number?), and use an ordinary std::map, to look up CreditCards by their number.
It's not appropriate for ChangeBalance to have const semantics. By the very nature of it's name, you're modifying the object. Make the function non-const.
void ChangeBalance(int amount) {
balance += amount;
}
The other problem is that you didn't call your function correctly. You should instead do this:
iter->ChangeBalance(chargeAmount);
I will mention there are cases where you want to modify values in a const object, and there is a mutable type modifier for that. Do not use it to solve your current error, however!
void ChangeBalance(int amount) should not be const - it is changing the object.
The problem is before in the iterator: cards.find returns a const object, so you are not allowed to change it.
A way to resolve that is to make your cards set a set of pointers to cards, not of cards; or to use another way to find the matching card
Playing fast and loose with the C++ syntax in that thar code, Hoss. Plenty of errors wait around the corner
First Error:
iter->CreditCard::ChangeBalance(chargeAmount);
should be
iter->ChangeBalance(chargeAmount);
Straight-up bad syntax that likely results from flailing around because of the errors resulting from unordered_set having no idea how to hash a CreditCard. Give this a read: How do I use unordered_set? That said, unordered_set is probably not the right solution for this job. std::map<std::string, CreditCard> looks more on point.
Using the wrong solution to fix the above problem lead to the
Second Error:
void ChangeBalance(int amount) const
const on a method means the method cannot change the state of the object. in ChangeBalance balance += amount; attempts to change the state of the object by updating a member variable.
In addition, the compiler is going to HATE the CreditCard:: in this:
CreditCard::CreditCard(string in_cardHolder, string in_cardNumber, int in_limit) {
cardHolder = in_cardHolder;
cardNumber = stoll(in_cardNumber);
limit = in_limit;
balance = 0;
}
Another solution is to make the "balance" as a static member.
class CreditCard {
private:
string cardHolder;
unsigned long long cardNumber;
int limit;
static int balance;
....
}
And then initialize it in cpp file
int CreditCard::balance = 0;
This code may not be very secure. But this can be one of the workaround.

C++ global extern constant defined at runtime available across multiple source files

I have an integer constant that is to be defined at runtime. This constant needs to be available globally and across multiple source files. I currently have the following simplified situation:
ClassA.h declares extern const int someConstant;
ClassA.cpp uses someConstant at some point.
Constants.h declares extern const int someConstant;
main.cpp includes ClassA.h and Constants.h, declares const int someConstant, and at some point during main() tries to initialize someConstant to the real value during runtime.
This works flawlessly with a char * constant that I use to have the name of the program globally available across all files, and it's declared and defined exactly like the one I'm trying to declare and define here but I can't get it to work with an int.
I get first an error: uninitialized const ‘someConstant’ [-fpermissive] at the line I'm declaring it in main.cpp, and later on I get an error: assignment of read-only variable ‘someConstant’ which I presume is because someConstant is getting default initialized to begin with.
Is there a way to do what I'm trying to achieve here? Thanks in advance!
EDIT (per request from #WhozCraig): Believe me: it is constant. The reason I'm not posting MCVE is because of three reasons: this is an assignment, the source is in Spanish, and because I really wanted to keep the question as general (and reusable) as possible. I started out writing the example and midway it striked me as not the clearest question. I'll try to explain again.
I'm asked to build a program that creates a process that in turn spawns two children (those in turn will spawn two more each, and so on). The program takes as single argument the number of generations it will have to spawn. Essentially creating sort of a binary tree of processes. Each process has to provide information about himself, his parent, the relationship with the original process, and his children (if any).
So, in the example above, ClassA is really a class containing information about the process (PID, PPID, children's PIDs, degree of relation with the original process, etc). For each fork I create a new instance of this class, so I can "save" this information and print it on screen.
When I'm defining the relationship with the original process, there's a single point in which I need to know the argument used when calling the program to check if this process has no children (to change the output of that particular process). That's the constant I need from main: the number of generations to be spawned, the "deepness" of the tree.
EDIT 2: I'll have to apologize, it's been a long day and I wasn't thinking straight. I switched the sources from C to C++ just to use some OO features and completely forgot to think inside of the OO paradigm. I just realized while I was explaining this that I might solve this with a static/class variable inside my class (initialized with the original process), it might not be constant (although semantically it is) but it should work, right? Moreover I also realized I could just initialize the children of the last generation with some impossible PID value and use that to check if it is the last generation.
Sorry guys and thank you for your help: it seems the question was valid but it was the wrong question to ask all along. New mantra: walk off the computer and relax.
But just to recap and to stay on point, it is absolutely impossible to create a global constant that would be defined at runtime in C++, like #Jerry101 says?
In C/C++, a const is defined at compile time. It cannot be set at runtime.
The reason you can set a const char *xyz; at runtime is this declares a non-const pointer to a const char. Tricky language.
So if you want an int that can be determined in main() and not changed afterwards, you can write a getter int xyz() that returns a static value that gets initialized in main() or in the getter.
(BTW, it's not a good idea to declare the same extern variable in more than one header file.)
As others have mentioned, your variable is far from being constant if you set it only at run-time. You cannot "travel back in time" and include a value gained during the program's execution into the program itself before it is being built.
What you can still do, of course, is to define which components of your program have which kind of access (read or write) to your variable.
If I were you, I would turn the global variable into a static member variable of a class with a public getter function and private setter function. Declare the code which needs to set the value as a friend.
class SomeConstant
{
public:
static int get()
{
return someConstant;
}
private:
friend int main(); // this should probably not be `main` in real code
static void set(int value)
{
someConstant = value;
}
static int someConstant = 0;
};
In main:
int main()
{
SomeConstant::set(123);
}
Anywhere else:
void f()
{
int i = SomeConstant::get();
}
You can further hide the class with some syntactic sugar:
int someConstant()
{
return SomeConstant::get();
}
// ...
void f()
{
int i = someConstant();
}
Finally, add some error checking to make sure you notice if you try to access the value before it is set:
class SomeConstant
{
public:
static int get()
{
assert(valueSet);
return someConstant;
}
private:
friend int main(); // this should probably not be `main` in real code
static void set(int value)
{
someConstant = value;
valueSet = true;
}
static bool valueSet = false;
static int someConstant = 0;
};
As far as your edit is concerned:
Nothing of this has anything to do with "OO". Object-oriented programming is about virtual functions, and I don't see how your problem is related to virtual functions.
char * - means ur creating a pointer to char datatype.
int - on other hand creates a variable. u cant declare a const variable without value so i suggest u create a int * and use it in place of int. and if u are passing it into functions make it as const
eg: int *myconstant=&xyz;
....
my_function(myconstant);
}
//function decleration
void my_function(const int* myconst)
{
....
}
const qualifier means variable must initialized in declaration point. If you are trying to change her value at runtime, you get UB.
Well, the use of const in C++ is for the compiler to know the value of a variable at compile time, so that it can perform value substitution(much like #define but much more better) whenever it encounters the variable. So you must always assign a value to a const when u define it, except when you are making an explicit declaration using extern. You can use a local int to receive the real value at run time and then you can define and initialize a const int with that local int value.
int l_int;
cout<<"Enter an int";
cin>>l_int;
const int constNum = l_int;

static members and encapsulation in c++

Let us assume the following class:
class FileManipulator
{
static InputTypeOne * const fileone;
InputTypeTwo *filetwo;
public:
FileManipulator( InputTypeTwo *filetwo )
{
this->filetwo = filetwo;
}
int getResult();
};
FileManipulator uses data from both files to obtain output from getResult(). This means multiple iterations over filetwo and multiple constructions of FileManipulators via iterations for different InputTypeTwo objects. Inputs are, let us say, some .csv databases. InputTypeOne remains the same for the whole task.
The program itself is multi-modular and the operation above is only its small unit.
My question is how can I handle that static field in accordance with the object-oriented paradigm and encapsulation. The field must be initialized somehow since it is not a fixed value over different program executions. As far as I understand C++ rules I cannot create a method for setting the field, but making it public and initializing it outside of any class (FileManipulator or a befriended class) seems to me at odds with the encapsulation.
What can I do then? The only thing that comes to my mind is to do it in a C manner, namely initialize it in an isolated enough compilation unit. Is it really all I can do? How would that be solved in a professional manner?
edit
I corrected pointer to constant to constant pointer, which was my initial intention.
You can write a public static method of FileManipulator that would initialize the field for you:
static void init()
{
fileone = something();
}
And then call it from main() or some place where your program is being initialized.
One way of doing this which comes to mind is:
In the .cpp file
FileManipulator::fileone = NULL;
Then modify constructor to do the following:
FileManipulator( InputTypeTwo *filetwo, InputTypeOne *initValue = NULL)
{
if(fileone == NULL)
{
fileone = initValue;
}
this->filetwo = filetwo;
}
Or you could also define an init function and make sure to call it before using the class and after the CTOR. the init function will include the logic of how to init fileone.

updating variable between functions in c++

My main program is to generate a random number to create movement of a object in a 2 dimensional array and to keep track of it.
one of my function void current_row(int row){position = row}; keeps track of the current row of the object.
since the variable is not global. i am finding problems calling the current location and updating it to the next movement. this is how the other function may look like:
void movement (){
int row;
row = current_row();
/*
* Here is the problem i'm having. This may well be
* a third function which has the same information
* as my first function. But still how do I access
* once without modifying it and access it
* again to update it?
*/
// call another function that creates new row.
// update that info to the row
}
i am new to c++.
Use an instance variable to keep track of it. That's why instance variables exist: To hold their values between function calls.
In case it's an OOP environment (as C++ tag implies), some class should declare int row as a class member (including a getter and a setter as methods).
Another option is declaring the variable at the head of the main() part of the program and call functions with row as a function parameter.
void movement(int row)
{
}
You can consider the parameter be passed by reference if you are intending to change it, otherwise it would be better declaring it const inside the function parameter declaration. If part of the answer sounds unfamiliar to you I would suggest reading through :
What's the difference between passing by reference vs. passing by value?

Why must my global variable be declared as a pointer?

When compiling my C++ program I receive no errors, however within unordered_map the hash function fails, attempting to mod by 0. (Line 345 of hashtable_policy.h of stl)
I've found a fix, but don't know why I'm having the problem to begin with.
My struct looks like this, (Sorry for the specific code.)
struct Player {
private:
Entity& entity = entityManager->create();
public:
Player() {
entity.addComponent(new PositionComponent(0, 0)); // Add component uses the unordered map.
}
};
Player playerOne; // Error perpetuates through constructor.
However, if I declare playerOne as a pointer, like so:
Player* playerOne;
and then call:
playerOne = new Player();
I do not have any issues.
I've been searching - with no success. What could I be doing wrong?
When you use a Player as a global, you've no idea if the entityManager (presumably another global) has been initialised yet - the order of initialisation of globals isn't defined.
When you use the pointer and initialise it with new (in main(), I presume), all the globals have been created by then, so the code works.
This highlights one of the reasons why global variables are a bad idea.