Below are my codes...
main.cpp
/* header files are included here */
PCI_card card;
int main(void)
{
card.init_card(0);
return 0;
}
pci_card.h
#ifndef __PCI_CARD_H
#define __PCI_CARD_H
/* header files are included here */
typedef struct {
int32_t card_index;
int32_t user_counter;
} card_dev_t;
class PCI_card {
public:
PCI_card() : dev_descriptor(-1) { enlarge_vector(); }
int32_t init_card(int32_t card_num);
private:
int32_t dev_descriptor;
public:
static int32_t enlarge_vector();
private:
static int32_t card_amount;
static std::vector<card_dev_t> cards;
};
#endif
pci_card.cpp
/* header files are included here */
int32_t PCI_card::card_amount = -1;
std::vector<card_dev_t> PCI_card::cards;
int32_t PCI_card::init_card(int32_t card_num)
{
if (card_num >= card_amount || card_num < 0)
return -1;
card_dev_t new_card = {
.card_index = card_num,
.user_counter = 1
};
cards[card_num] = new_card;
dev_descriptor = card_num;
return 0;
}
int32_t PCI_card::enlarge_vector()
{
card_amount = 10;
card_dev_t null_card = {
.card_index = -1,
.user_counter = -1
};
cards.resize(card_amount, null_card);
return card_amount;
}
In main.cpp, card is defined as a global variable, and of course, it should be initialized before invoking main() function, and this can be seen clearly via gdb.
When initializing card, constructor of class PCI_card is invoked, the vector cards in this class is resized according to card_amount member variable. From the gdb, this vector does be initialized properly, it contains 10 elements.
Weird things happened before invoking main() function, the vector is reset. In gdb, the size of vector rolled back to 0, and of course, subsequent operations, such as subscript this vector, cause segment fault error.
I don't know what happen here.... it is too ridiculous...
It looks like you have hit a static initialization order fiasco. It is possible that PCI_card card; initialization will happen before std::vector<card_dev_t> PCI_card::cards. If that happen (and standard allows it) then PCI_card::enlarge_vector() will call resize (here enter UB) on not yet initialized vector. After its execution normal static initialization of PCI_card::cards will get executed - initializing vector to empty one. And this is why you see this behaviour:
In gdb, the size of vector rolled back to 0,
This is Undefined Behaviour so anything that you see in gdb is possible.
The solution is to either make cards non static, or use a static function with static field which will return it:
std::vector<card_dev_t>& getCards() {
static std::vector<card_dev_t> cards;
return cards;
}
this will ensure that cards will get initialized on first use of getCards.
Related
This question already has answers here:
Can a local variable's memory be accessed outside its scope?
(20 answers)
Closed 8 months ago.
I would like to know how I can make a function's variable public to other functions.
Example:
void InHere
{
int one = 1; // I want to be public
}
int main()
{
InHere(); // This will set int one = 1
one = 2; // If the variable is public, I should be able to do this
return 0;
}
Does anyone know how to do this? The only things I find when searching is for classes, as you can see nothing is in a class and I don't want them to be in one.
Any help is really appreciated!
A variable defined locally to a function is generally inaccessible outside that function unless the function explicitly supplies a reference/pointer to that variable.
One option is for the function to explicitly return a reference or pointer to that variable to the caller. That gives undefined behaviour if the variable is not static, as it does not exist after the function returns.
int &InHere()
{
static int one = 1;
return one;
}
void some_other_func()
{
InHere() = 2;
}
This causes undefined behaviour if the variable one is not static since, as far as the program as a whole is concerned, the variable only comes into existence whes InHere() is called and ceases to exist as it returns (so the caller receives a dangling reference - a reference to something that no longer exists).
Another option is for the function to pass a pointer or reference to the variable as an argument to another function.
void do_something(int &variable)
{
variable = 2;
}
int InHere()
{
int one = 1;
do_something(one);
std::cout << one << '\n'; // will print 2
}
The downside is that this only provides access to functions CALLED BY InHere(). Although the variable does not need to be static in this case, the variable still ceases to exist as InHere() returns (so if you want to combine option 1 and option 2 in some way, the variable needs to be static)
A third option is to define the variable at file scope, so it has static storage duration (i.e. its lifetime is not related to the function);
int one;
void InHere()
{
one = 1;
}
void another_function()
{
one = 2;
}
int main()
{
InHere();
// one has value 1
some_other_function();
// one has value 2
}
A global variable can be accessed in any function that has visibility of a declaration of the variable. For example, we could do
extern int one; // declaration but not definition of one
int one; // definition of one. This can only appear ONCE into the entire program
void InHere()
{
one = 1;
}
And, in other source file
extern int one; // this provides visibility to one but relies on it
// being defined in another source file
void another_function()
{
one = 2;
}
int main()
{
InHere();
// one has value 1
some_other_function();
// one has value 2
}
Be careful with that though - there are numerous down-sides of global/static variables, to the extent they are usually considered VERY BAD programming technique. Have a look at this link (and pages linked to from there) for a description of some of the problems.
Just set the variable as a global variable. Then you can access it from other functions.
int one;
void InHere()
{
one = 1; // I want to be public
}
int main()
{
InHere(); // This will set int one = 1
one = 2; // If the variable is public, I should be able to do this
return 0;
}
if you want it inside a class, then try the code below
#include <iostream>
using namespace std;
class My_class
{
// private members
public: // public section
// public members, methods or attributes
int one;
void InHere();
};
void My_class::InHere()
{
one = 1; // it is public now
}
int main()
{
My_class obj;
obj.InHere(); // This will set one = 1
cout<<obj.one;
obj.one = 2; // If the variable is public, I should be able to do this
cout<<obj.one;
return 0;
}
This question already has answers here:
Constructor to specify zero-initialization of all builtin members?
(3 answers)
Closed 8 years ago.
What is the best way to make sure the following large struct always has its integers initialized to 0?
struct Statistics {
int num_queries;
int num_respones;
// ... 97 more counters here
int num_queries_filtered;
}
I would like to avoid having to check each place this struct is initialized to make sure it is value initialized with Statistics s(); rather than default initialized with Statistics s;.
Statistics s; // Default initialized by accident here
s.num_queries++; // Oh no, this is a bug because it wasn't initialized to zero
Statistics s2{}; // Correctly value initialized
s2.num_queries++; // Successful
Proposal 1 - Use memset, but this feels like a hack where we take advantage of the value initialization happening to be equivalent to 0 filling the data structure:
struct Statistics {
Statistics() { memset(this, 0, sizeof(*this)); }
// ... counters here
}
Proposal 2 - Use constructor initialization lists, but this is cumbersome and when people add new counters in the future they may forget to zero-initialize them in the constructor:
struct Statistics {
Statistics() : num_queries(0), num_respones(0), /* ... */, num_queries_filtered(0) {}
// ... counters here
}
Proposal 3 - Force the value initialization to take place as follows:
struct StatisticsUnsafe {
// ... counters here
}
struct Statistics : public StatisticsUnsafe {
Statistics() : StatisticsUnsafe() {}
}
What do you feel is the best approach? Do you have other alternatives?
EDIT I want to clarify that in my actual code, each of the counters has a meaningful name, such as "num_queries_received", "num_responses", etc. Which is why I do not opt to use a vector or array of the form "counters[100]"
EDIT2 Changed the example from Statistics s2(); to Statistics s2{};
From C++11, you may also do:
struct Statistics {
int counter1 = 0;
int counter2 = 0;
// ... more counters here
int counter100 = 0;
};
Unless you have a fairly specific reason to do otherwise, your first choice should probably be a std::vector, such as:
std::vector<int> Statistics(100);
This will zero all the contents automatically. You can address an individual counter in the array as something like:
++Statistics[40];
...which will increment the 41st item (the first is Statistics[0]).
If the size if really fixed at 100 (or some other number you know at compile time) you might prefer to use std::array instead:
std::array<int, 100> Statistics;
This is potentially a little faster and usually uses a (little) less memory, but fixes the size (whereas with an std::vector you can use push_back, erase, etc., to add and remove items).
Given the edited question (the objects really aren't array-like) I'd probably consider something a little different, probably something like this:
template <class T>
class inited {
T val;
public:
inited(T val=T()) : val(val) {}
operator T() const { return val; }
operator=(T const &newval) { val = new_val; }
};
struct Statistics {
inited<int> sum;
inited<int> count;
inited<double> mean;
};
Then an inited<T> is always initialized to some value--you can specify a value if you wish, and if you don't specify any, it uses value initialization (which will give zero for arithmetic types, a null pointer for a pointer type, or use the default constructor for types that define one).
Since it defines an operator T and an operator=, you can still assign to/from elements, just about like usual:
Statistics.sum = 100;
Statistics.count = 2;
Statistics.mean = static_cast<double>(Statistics.sum) / Statistics.count;
You might prefer to use a single:
operator T&() { return val; }
Instead though. This supports both reading and writing (as above) but also compound assignment operators (e.g., += and -=).
Have you considered writing an initializer for each data member?
struct Statistics {
typedef int counter_t;
counter_t counter1 = 0;
counter_t counter2 = 0;
// ... more counters here
counter_t counter100 = 0;
};
Note that if you include such initializers, though, the struct is no longer an aggregate, and hence can't be initialized using aggregate initialization via a braced list. Whether that matters or not for this type is hard to say.
Well you certainly can do something like:
struct Statistics {
int counter1 = 0;
int counter2 = 0;
// ... more counters here
int counter100 = 0;
};
This is perfectly valid in c++11. But the question is, do you really need this? Wouldn't it be more convenient to use a vector?
struct Statistics {
std::vector<int> counters = std::vector<int>(100, 0);
};
And if vector is not an option, you can do some magic in constructor:
struct Statistics {
int counter1;
int counter2;
// ... more counters here
int counter100;
Statistics() {
for (int * i : {&counter1, &counter2, ..., &counter100 }) {
*i = 0;
}
}
};
Statistics s;
s.counter2; // now stores 0 or anything you like.
Here is a C-like way:
#include <assert.h>
#include <cstring>
#include <type_traits>
struct Statistics {
int counter1;
int counter2;
int counter3;
int counter4;
// maybe more //
Statistics() {
// checks whether Statistics is standard-layout
// to be sure that memset won't break it
static_assert(
std::is_standard_layout<Statistics>(),
"Someone broke Statistics, can't use memset to zero it.");
// initializes hole Statistics's memory by zeros
memset(this, 0, sizeof(Statistics));
}
};
// Here is a way how to check Statistics
void assert_Statistics() {
Statistics s;
int* ptr = reinterpret_cast<int*>(&s);
int count = sizeof(Statistics) / sizeof(int);
for (int i = 0; i < count; ++i) {
assert(*(ptr++) == 0);
}
}
int main()
{
Statistics s;
assert_Statistics();
}
takeaway.o: In function `takeaway':
project:145: undefined reference to `vtable for takeaway'
project:145: undefined reference to `vtable for takeaway'
takeaway.o: In function `~takeaway':
project:151: undefined reference to `vtable for takeaway'
project:151: undefined reference to `vtable for takeaway'
takeaway.o: In function `gameCore':
project.h:109: undefined reference to `gameCore<int>::initialData(int)'
collect2: ld returned 1 exit status
make: *** [takeaway] Error 1
I keep getting this Error from the linker , i know it has something to do with inline functions getting a vtable temporarily stored. But what that entails i am not quite sure. I would assume it has something to do with how i call gameCore's constructor in the initilization list of takeaway.cpp
I have a templated class (gameCore.h)
and a class (takeaway.cpp) that is inheriting from gameCore
The vtable error is called 3 times
1)in takeaways constructor
2) takeaways destructor
3)in gameCores constructor
I am using G++
Here is the code:
(i know it may seem hard to read but i have marked off exatcly where the erros occur)
takeaway.h
#ifndef _TAKEAWAY_H_
#define _TAKEAWAY_H_
#include<map>
#include<cctype>
#include<stack>
#include<map>
#include<iostream>
#include<string>
#include<cstdlib>
#include"gameCore.h"
#include<vector>
using namespace std;
class takeaway : public gameCore<int>
{
private:
public:
// template<class Penny>
void textualGame();
bool isNum(string str);
// template<class Penny>
stack<int> initialData(int initial);
// template<class Position>
int score (int position);
// template<class Position>
stack<int> addStack(int currentPos, stack<int> possiblePositions);
// template<class Penny>
takeaway (int initial);
// template<class Position>
~takeaway();
};
bool isNum(string str);
int charToint(char *theChar);
#endif
takeaway.cpp
/*
Description :
This game communicates with the gameCore class to determine the results
of a game of takeaway played between two computers or a computer and human.
*/
#include "takeaway.h"
/*
Description:Creates a stack represening initial data
Note:Change to a vector eventually
return : stack of int
*/
stack<int> takeaway:: initialData(int initial){
stack<int> returnStack;
int theScore = score(initial);
int final;
if(initial ==0)
{
final = 1;
}
else
{
final = 0;
}
returnStack.push(theScore);
returnStack.push(final);
return returnStack;
}
/*
Description: a textual representation of the game
Note: This is still terribly wrong
*/
void textualGame(){
cout <<"this is the best i could do for a graphical representation";
}
/*
Description: Deetermines if a number is even
Note: Helper function for determining win or loss positions
Returns: 1 if it is and 0 if it is not
*/
int takeaway::score(int position){
if(position % 2 == 0)
{
return 1;
}
return 0;
}
/*
Description: Will return a stack , withouth the given postion in it
will contain all positions possible after the given position
along with anyother that wehre in the given stack.This function
Must also update the map to represent updated positions
Takes: a position to check and a stack to return
Returns: A stack of possible positions.
*/
stack<int> takeaway::addStack(int currentPos, stack<int> possiblePositions ){
if(currentPos != 0)
{
// If even
if( currentPos % 2 == 0)
{
// Create a data aray with score of the new positon and mark it as not final
int data[] = {score(currentPos/2),0};
vector<int> theData(data, data+sizeof(data));
int pos = currentPos/2;
// Add it to the map
//this -> gamesMap[currentPos/2] = dataArray;
this -> gamesMap.insert(std::pair<int, vector<int> >(pos, theData));
// Add it to the possible positions
possiblePositions.push(pos);
}
if(currentPos % 3 == 0)
{
int data[] = {score(currentPos/3),0};
vector<int> theData(data,data+sizeof(data));
int pos = currentPos/3;
//this -> gamesMap[currentPos/3] = dataArray;
this -> gamesMap.insert(std::pair<int, vector<int> >(pos, theData));
possiblePositions.push(pos);
}
// Work for the position that represents taking one penny
int minusFinal = 0;
if(currentPos - 1 == 0)
{
minusFinal = 1;
}
int data[] = {score(currentPos - 1),minusFinal};
vector<int> theData(data,data+sizeof(data));
int pos = currentPos - 1;
// this -> gamesMap[currentPos -1] = dataArary
this->gamesMap.insert(std::pair<int,vector<int> >(pos, theData));
possiblePositions.push(pos);
}
return possiblePositions;
}
/*
Description: Constructor for the takeaway game
OA takes: a initial position, and initial data for it
*/
takeaway::takeaway(int initial):gameCore<int>::gameCore(initial){ //<--- ERROR HERE
//Constructor
}
/*
Description: Destuctor
*/
takeaway::~takeaway(){ // <--------------------- ERROR HERE
//Destructor
}
//checks input and creates game.
int main(int argc, char* argv[]){
int numberPennies ;
string game = argv[0];
if(argc == 2 && isNum(argv[1]) )
{
int pennies = charToint(argv[1]);
takeaway gameInstance(pennies ); // Creates a instance of $
}
// else if(argc == 3 && argv[1] == "play" && isNum(argv[2]) )
// {
// int pennies = charToint(argv[2]);
// takeaway<int> gameInstance(pennies); // Craete a human playab$
// }
else
{
cerr << "Error->Usage: " << game <<" [play] numberOfPennies \n";
exit (1);
}
return 0;
}
//Converts a char to a integer
int charToint(char *theChar){
int theInt = atoi(theChar);
return theInt;
}
//Determines if a string is numeric
bool isNum(string str){
for(int i = 0;i < str.length() ;i++){
if(isdigit(str[i]) != 1)
{
cerr << "Error->Input: Number must be a Positive Integer the charecter '" << str[i]<< "' invalidated your input. \n" ;
exit(1);
return false;
}
}
return true;
}
gameCore.h
/*
gameCore.h
Description:
This class created gameMap that are written as a template
They will communicate with the specific game and the algorithm
To keep track of positions ans there values.
*/
#ifndef GAMECORE_H
#define GAMECORE_H
#include <map>
#include <stack>
#include <string>
#include <vector>
using namespace std;
template <class Position>
class gameCore
{
protected:
//Best Move used by algorithim
Position bestMove;
//The current highest score used by the algorithim
int highestScore ;
//Stack to be used to remmeber what move created the score
stack<Position> movedFrom;
//Stack used for the algorithim.
stack<Position> curWorkingPos;
//The actual Map that the data will be held in.
map<Position,vector<int> > gamesMap;
public:
/*
Description : finds the data array for a poisition
takes: a Position
Returns: a array of integers /**
*/
virtual stack<int> initialData(Position pos) = 0;
/*
Description: Game must implement a way to determine a positions
score.
*/
virtual int score(Position pos) = 0;
/*
Description: A Graphical representation of the game
*/
virtual void textualGame() = 0;
/*
Description: a virtual function implemented by the child class
it will return a stack without the given position in it.This stack
will contain all positions available from the given postion as well as
all position already in the given stack. Also it will update the map with
all generated positions.
TAkes: a postion to check and a stack of currently working positons.
*/
virtual stack<Position> addStack(Position currentPos, stack<Position> possiblePositions ) = 0;
/*
Description:Constructor that
Creates a Map with positions as the key.
And an array of two integers that represent the positions
value and if we have moved here in the past.
Takes: a Initial Position and a Array of integers
*/
gameCore(Position initial){ // <-----ERROR HERE
//Determine the initial data and add it to the map and queue.
stack<int> theData = initialData(initial);
int first = theData.top();
theData.pop();
int second = theData.top();
theData.pop();
int initialData[] = {first,second};
vector<int> posData(initialData,initialData+sizeof(initialData));
gamesMap[initial] = posData;
curWorkingPos.push(initial);
}
/*
Description:
A destructor for the class
*/
~gameCore(){
//I do nothing but , this class needs a destructor
}
/*
Description: Takes the current position and returns
that positions Score.
Takes: A position
Returns:A integer that is a positions score.
*/
int getPosScore(Position thePos) const {
return this ->gamesMap.find(thePos)->second[0];
}
/*
Description: Adds values to a stack based on the current position
Takes: a poistion
*/
void updateStack(Position curPos){
this ->curWorkingPos =addStack(curPos,this ->curWorkingPos ); // get a stack from the game
// The game has a function that takes a position and a stack and based on the positions returns a stack identical to the last but with added values that represent valid moves from the postion./
}
/*
Description : Takes a positions and returns a integer
that depends on if the position is a final pos or not
Takes: A position
Returns: A Bool that represents if the position is a final(1) or not (0).
*/
// Possible change
bool isFinal(Position thePos) {
typename map<Position,vector<int> >::iterator iter = this ->gamesMap.find(thePos);
return iter->second[1] == 1 ;
}
/*
Description: Based on the given position determine if a move needs to be made.
(if not this is a end game position and it will return itself) If a move needs
to be made it will return the position to move to that is ideal.
Note: (because all positions can be represented as integers for any game , the return
type is a integer)
*/
int evaluatePosition(Position possiblePosition ){
if(isFinal(possiblePosition)) //If this is a final position
{
return getPosScore(possiblePosition); //Return the score
}
else
{
updateStack(possiblePosition); //Put all possible positions from this in thte stack
while(this -> curWorkingPos.size() != 0)
{
this -> movedFrom.push(this->curWorkingPos.front()); //take the top of the possible positions stack and set it the the moved from stack
this -> curWorkingPos.pop();
int curScore = evaluatePosition(this ->movedFrom.top()); //Recursive call for school
curScore = curScore * -1; //Negate the score
if(curScore > this -> highestScore) // if the score resulting from this position is biggest seen
{
highestScore = curScore;
this ->movedFrom.pop(); //do this first to get rid of the the lowest point
this -> bestMove = this ->movedFrom.top(); // mark where the lowest point came from
}
else
{
this -> movedFrom.pop();
}
}
}
return this -> bestMove;
}
//A Structure to determine if a position has a lower value than the second
struct posCompare{
bool operator() (Position pos1,Position pos2) const {
return (pos1.getPosScore() < pos2.getPosScore());
}
};
};
#endif
One or more of your .cpp files is not being linked in, or some non-inline functions in some class are not defined. In particular, takeaway::textualGame()'s implementation can't be found. Note that you've defined a textualGame() at toplevel, but this is distinct from a takeaway::textualGame() implementation - probably you just forgot the takeaway:: there.
What the error means is that the linker can't find the "vtable" for a class - every class with virtual functions has a "vtable" data structure associated with it. In GCC, this vtable is generated in the same .cpp file as the first listed non-inline member of the class; if there's no non-inline members, it will be generated wherever you instantiate the class, I believe. So you're probably failing to link the .cpp file with that first-listed non-inline member, or never defining that member in the first place.
The first set of errors, for the missing vtable, are caused because you do not implement takeaway::textualGame(); instead you implement a non-member function, textualGame(). I think that adding the missing takeaway:: will fix that.
The cause of the last error is that you're calling a virtual function, initialData(), from the constructor of gameCore. At this stage, virtual functions are dispatched according to the type currently being constructed (gameCore), not the most derived class (takeaway). This particular function is pure virtual, and so calling it here gives undefined behaviour.
Two possible solutions:
Move the initialisation code for gameCore out of the constructor and into a separate initialisation function, which must be called after the object is fully constructed; or
Separate gameCore into two classes: an abstract interface to be implemented by takeaway, and a concrete class containing the state. Construct takeaway first, and then pass it (via a reference to the interface class) to the constructor of the concrete class.
I would recommend the second, as it is a move towards smaller classes and looser coupling, and it will be harder to use the classes incorrectly. The first is more error-prone, as there is no way be sure that the initialisation function is called correctly.
One final point: the destructor of a base class should usually either be virtual (to allow polymorphic deletion) or protected (to prevent invalid polymorphic deletion).
If a class defines virtual methods outside that class, then g++ generates the vtable only in the object file that contains the outside-of-class definition of the virtual method that was declared first:
//test.h
struct str
{
virtual void f();
virtual void g();
};
//test1.cpp
#include "test.h"
void str::f(){}
//test2.cpp
#include "test.h"
void str::g(){}
The vtable will be in test1.o, but not in test2.o
This is an optimisation g++ implements to avoid having to compile in-class-defined virtual methods that would get pulled in by the vtable.
The link error you describe suggests that the definition of a virtual method (str::f in the example above) is missing in your project.
You may take a look at this answer to an identical question (as I understand):
https://stackoverflow.com/a/1478553
The link posted there explains the problem.
For quick solving your problem you should try to code something like this:
ImplementingClass::virtualFunctionToImplement(){...}
It helped me a lot.
Missing implementation of a function in class
The reason I faced this issue was because I had deleted the function's implementation from the cpp file, but forgotten to delete the declaration from the .h file.
My answer doesn't specifically answer your question, but lets people who come to this thread looking for answer know that this can also one cause.
it suggests that you fail to link the explicitly instantiated basetype public gameCore (whereas the header file forward declares it).
Since we know nothing about your build config/library dependencies, we can't really tell which link flags/source files are missing, but I hope the hint alone helps you fix ti.
GNU linker, in my case companion of GCC 8.1.0, well detects not re-declared pure virtual methods, but above certain complexity of class design it fails to identify missing implementation of methods and answers with a flat "V-Table Missing",
or even tends to report missing implementation, in spite it is there.
The only solution then is to verify consistency of declaration of implementation manually, method by method.
if you have virutal deconstruct function, you need to write it like this: ~SubListener() override = default; , don't forget this =default
Okay, so, I am storing a public integer in a class, like this:
class varglobalness{
public:
int xp;
int lvl;
int xpt;
int hp;
};
and, inside of a function I am trying to change the variables by doing this:
v.lvl += 1;
v.xpt += rand()%25+25;
v.xp = 0;
v.hp += rand()%25+5;
When I do this, though, hp doesn't change, xp does change to 0, but xpt and lvl changes to a lot of random numbers.
Any idea how I can properly change these integers without this happening?
Sounds like you're not properly initialising them. If a variable is uninitialised, it'll have an undefined value. You can give them initial values in the constructor:
// varglobalness.h:
class varglobalness {
public:
varglobalness();
// ...
};
// varglobalness.cpp:
varglobalness::varglobalness() : xp(0), lvl(0), xpt(0), hp(0) {}
Or assign them initial values elsewhere, as you prefer. As an aside, you ought to be putting these variables somewhere meaningful and encapsulated, rather than in a bundle of random globals.
Did you initialize the variables? Variables in C++ don't initialize themselves.
//In your constructor
v.lvl = 1;
v.xpt = 0;
v.xp = 0;
v.hp = 0;
#include <iostream>
using namespace std;
class t
{ public:
int health; //its members
int speed;
int power;
void attack() // its methods
{ cout<<"I'm attacking"<<endl;
};
};
int main()
{ t A,B,C,D;
A.power = 100;
B.health = 87;
C.speed = 92;
cout<<"A= "<<A.power<<"B= "<<A.health<<"C= "<<A.speed<<endl; // <---
cout<< "My health is "<<C.health<<" My speed is "<<A.speed<<endl;
cout<<"My power is "<<B.power<<endl;
D.attack();
system("pause");
return 0;}
The output result was ::
A= 100 B= 96 C=6234392 <--- From where these values come
A.health and A.speed are just junk values on the stack because you didn't explicitly set them. If you want to initialize all fields of A to zero, you can use memset:
memset(&A, 0, sizeof(A));
You should create a constructor to initialize those values to some default value in the initializer list.
class t {
public:
t() : health(100),power(100),speed(100) {}
// ...
};
This will guarantee that those values are all set to 100, or some default, or even an input parameter, rather than garbage. It's considered much better design since otherwise the initialization of those values would be handled in the constructor that the compiler generates for you behind the scenes.
Uninitialized memory?
Uninitialized variable won't be zero setted at the creation of the class/struct. You need to manualy do it. Otherwise, you will get whatever_is_in_memory_at_that_time.