I think the mistake i'm doing it's so stupid but i don't know what i'm doing wrong.
I have a class with static and non-static vars and some methods, all public.
In my program i want to create an object and pass this object to a general method by reference.
The program doesn't compile and the compiler throws really weird error messages.
Undefined symbols for architecture x86_64: "prueba::num", referenced
from:
_main in ccbRZYqe.o
metodoC(prueba*) in ccbRZYqe.o
prueba::prueba()in ccbRZYqe.o
prueba::inicio() in ccbRZYqe.o "prueba::flag", referenced from:
metodoC(prueba*) in ccbRZYqe.o
prueba::prueba()in ccbRZYqe.o
prueba::inicio() in ccbRZYqe.o ld: symbol(s) not found for architecture x86_64 collect2: ld returned 1 exit status
Code
#include <iostream>
using namespace std;
class prueba
{
private:
public:
static bool flag;
static int num;
float complejo;
// Metodos
//--------------
prueba()
{
flag = false;
num = 0;
complejo = 0.0;
}
void inicio()
{
flag = true;
num = 5;
complejo = 3.2;
}
bool cambio()
{
flag++;
num++;
complejo++;
}
};
bool metodoC(prueba* ensayo)
{
cout << "-----------------------------------------" << endl;
cout << "- flag: " << ensayo->flag << endl;
cout << "- num: " << ensayo->num << endl;
cout << "- Complejo: " << ensayo->complejo << endl;
cout << "-----------------------------------------" << endl;
return true;
}
//-----------------------------------
// M A I N
//-----------------------------------
int main(int argc, char *argv[])
{
prueba test;
test.inicio();
test.num += 2;
test.complejo += 5.2;
metodoC( &test );
return 0;
}
You need to define your static members. They are only declared.
class prueba {
// as before
};
and in the implementation file:
bool prueba::flag=false;
int prueba::num=0;
Note that you shouldn't put the definitions in a header because you will get a definition of the statics for each translation unit. You need to put them in an implementation file that is then used to make a single object file that clients can build against.
Be careful though, each time you instantiate a new prueba object, you reset the static members in the constructor.
static members in class should be declared inside the class but define outside the class
`bool prueba::flag=false;`
int prueba::num=0;`
add these after class and remove their defination from inside the constructor .
It will work fine for you
I think the error is because the num value in prueba is declared as static, hence accessing it by: test.num will not work, and this is why the value is undefined.
If you change that to prueba::num += 2; it should work ok, also add in the appropriate initializers:
bool prueba::flag = false;
int prueba::num = 0;
Related
I am trying to make a simple game
What will happen is a player will be hit by various objects that result in increase/ decrease of health
The mainGame(); is created just to see if its working properly.
On compilation i get this
(.text$_ZN5gamer7setDataEv[__ZN5gamer7setDataEv]+0x117)||undefined reference to `gamer::mainGame()'|
I tried the friend keyword but that gave me the error of undefined reference to object
class gamer
{
public:
string gName;
int gHealth;
int continueGame;
void mainGame();
void setData()
{
cout << "Enter your name " <<endl;
cin >> gName;
srand(time(0));
gHealth = 100 + (rand()%200);
cout << gName << " has health of " << gHealth << endl;
cout << "Would you like to continue ? 0 for yes" << endl;
cin >> continueGame;
if (continueGame == 0)
{
mainGame();
}
}
};
void mainGame()
{
gamer gamer;
while(gamer.gHealth >= 0 || gamer.gHealth <= 500)
{
cout << " aaaaaa" << endl;
gamer.gHealth -= 50;
cout << gamer.gHealth << endl ;
}
}
You have declared the mainGame function as a member of your gamer class but never actually defined it. You came close, but forgot to declare, in the definition, that it a member of the class. The below should work:
void gamer::mainGame() // This is a member function of `gamer`, so declare it as such!
{
// gamer gamer; // We don't need this reference, as the member function will have...
while(gHealth >= 0 || gHealth <= 500) // ... an implied "this" object when called
{
cout << " aaaaaa" << endl;
gHealth -= 50; // Just using the member name on its own is enough to get it.
cout << gHealth << endl ;
}
}
Inside a member function, you don't need code declaring an object of that class! When the function is called (by an object of the class) the function effectively receives a pointer to the object that called it; you can explicitly access this pointer with the this keyword but, generally, you don't need to. Just using the name of a member variable in that function will reference that member variable for the object that called the function.
I have been trying to access a series of integers from the main class, and then display them inside a method.
However, I've been having a bit of trouble with this due to my own ineptitude with a language I've not been coding in for too long.
After quite a bit of searching, I have been unable to find anything that can help me. How would I go about doing this, if it's possible at all?
#include "inventory.h"
inventory::inventory(){
int maxhealth = 100;
int maxmana = 0;
int health = 100;
int mana = 0;
int level = 1;
int agility = 1;
int strength = 1;
int healthpotions = 0;
int manapotions = 0;
int armourlevel = 0;
int weaponlevel = 0;
int crystals = 0;
int gold = 0;
int rock = 0;
int wood = 0;
}
string inventory::getinv(){
return inventory; //I know this sort of return thing won't work, just a placeholder until I figure out what to do.
}
This is what I have been using thus far, but I'm having a hard time even getting that to not display the "Member 'X' was not initialized in this constructor." I'm clearly doing something quite wrong.
Inventory.h:
#ifndef INVENTORY_H_
#define INVENTORY_H_
#include <iostream>
class inventory{
private:
int maxhealth;
int maxmana;
int health;
int mana;
int level;
int agility;
int strength;
int healthpotions;
int manapotions;
int armourlevel;
int weaponlevel;
int crystals;
int gold;
int rock;
int wood;
public:
inventory();
string getinv();
};
#endif /* INVENTORY_H_ */
EDIT: Thanks to the help so far I've been able to get rid of most of the errors. The only one left is "..\src\zoria.cpp:1616:36: error: 'rock' was not declared in this scope"
You do not need the type in the constructor to access the member variables, otherwise the compiler would think that you are trying to declare new local variables.
Here is a basic correction for the inventory.cpp file:
#include "inventory.h"
inventory::inventory(){ // this is the constructor
maxhealth = 100;
maxmana = 0;
health = 100;
mana = 0;
level = 1;
agility = 1;
strength = 1;
healthpotions = 0;
manapotions = 0;
armourlevel = 0;
weaponlevel = 0;
crystals = 0;
gold = 0;
rock = 0;
wood = 0;
}
string inventory::getinv(){
return "inventory"; //I know this sort of return thing won't work, just a placeholder until I figure out what to do.
}
Note the "" added to the placeholder (return "inventory") to make it a valid string.
Note: You cannot access the variable that is in a class directly without an object of the class, even if it is declared public (static being the only exception). However you have declared all your member variables as private and will thus require getter and setter functions to access their values.
EDIT:
Classes are like containers which contain things. But just the definition of a class is just like a stencil which can be used to create objects of that type. The actual existence of the object occurs when you write inventory someobject;.
Now every class has a special function called the constructor which goes by the name of the class itself and is called as soon as the an object of this class is declared. You can initialize all member variables of the class in the constructor.
To access the members of a class you have to use the . dot operator. Members have to be declared public if they need to be directly accessed outside the class' body.
So you change the class definitions like this:
inventory.h:
#ifndef INVENTORY_H_
#define INVENTORY_H_
class inventory{
public:
int maxhealth;
int maxmana;
int health;
int mana;
int level;
int agility;
int strength;
int healthpotions;
int manapotions;
int armourlevel;
int weaponlevel;
int crystals;
int gold;
int rock;
int wood;
inventory();
void printinv();
};
#endif /* INVENTORY_H_ */
and
inventory.cpp:
#include "inventory.h"
#include <iostream>
using namespace std;
inventory::inventory()
{
maxhealth = 100;
maxmana = 0;
health = 100;
mana = 0;
level = 1;
agility = 1;
strength = 1;
healthpotions = 0;
manapotions = 0;
armourlevel = 0;
weaponlevel = 0;
crystals = 0;
gold = 0;
rock = 0;
wood = 0;
}
void inventory::printinv(){
cout << "LEVEL: " << level << endl;
cout << "HEALTH: " << health << endl;
cout << "MANA: " << mana << endl;
cout << "AGILITY: " << agility << endl;
cout << "STRENGTH: " << strength << endl;
cout << endl;
cout << "HEALTH POTIONS: " << healthpotions << endl;
cout << "MANA POTIONS: " << manapotions << endl;
cout << endl;
cout << "ARMOUR LEVEL: " << armourlevel << endl;
cout << "WEAPON LEVEL: " << weaponlevel << endl;
cout << "CRYSTALS: " << crystals << endl;
cout << endl;
cout << "GOLD: " << gold << endl;
cout << "ROCK: " << rock << endl;
cout << "WOOD: " << wood << endl;
}
Now declare the object of the class in main like:
inventory inv;
and access every member variable (such as maxhealth, maxmana, health, mana, level, agility, strength, healthpotions, manapotions, armourlevel, weaponlevel, crystals, gold, rock and wood) like:
inv.gold = 10;
inv.rock++;
etc. throughout the code.
and to display the inventory replace all the redundant display code with:
inv.printinv();
everywhere.
See zoria.cpp here, I have done the changes for all display code and changed the variable accesses for: maxhealth, maxmana, health and healthpotions you also have to do it for the rest of the variables like: mana, level, agility, strength, manapotions, armourlevel, weaponlevel, crystals, gold, rock and wood.
Hope this helps. Tell if there are any more questions.
In Inventory.h you define the member variables (maxhealth, maxmana etc) and in Inventory.cpp, you should declare them in its constructor. The problem is that you're redeclaring them. Try removing the "int" from every variable in the constructor because you only need to specify the type when you define the variable.
A few points here:
In you constructor you are shadowing the instance variables by method-local re-definition of identically named variables. Please, look up on how to initialize instance member variables in constructors.
You try to implicitly convert an instance of your inventory class into a std::string with the signature of your getinv() method, but you have not defined any operator for this kind of conversion.
(probably related to (2)) From the error you posted, I assume you are using getinv() something along the line of
inventory my_inventory{};
int inv = my_inventory.getinv();
This will not work as there is no implicit conversion from std::string to int defined. Change the return type of inventory::getinv() to int and return an actual int there.
I'm trying to instantiate a variable Tt1 from a class called ÌnletConditions with the variable Tt0 from another class with the object ein_in.
double InletConditions::Tt1 = ein_in.Tt0;
The variable Tt1 is declared as public static double in the headerfile of the class InletConditions.
class InletConditions {
public:
static double Tt1;
}
The variable Tt0 is declared and instantiated like this:
\\ file Eingabe_Konstanten.h
class Eingabe_Konstanten {
public:
static double Tt0;
}
\\ file Eingabe_Konstanten.cpp
double Eingabe_Konstanten::Tt0 = io_ein.read(1);
io_ein.read(int) refers to a method, which reads in a value from the specified line number (int) from a file. The value should become 293.15.
How can I achieve that the value of Tt1 also becomes 293.15? In the output it is just 0.
int main() {
Eingabe_Konstanten ein;
InletConditions in;
std::cout << ein.Tt0 << endl;
std::cout << in.Tt1 << endl;
}
Output:
293.15
0
I would be pleased if anyone could help me, since I am new to programming and don't know what topic this problem is related to.
Thanks in advance.
Static variables refer to the class itself and not to a particular object of that class. As such you must call them using the scope resolution operator of the class:
InletConditions::Tt1 = Eingabe::Tt0;
std::cout << Eingabe::Tt0 << endl;
std::cout << InletConditions::Tt1 << endl;
LIVE DEMO
Why not just use:
int main() {
Eingabe_Konstanten ein;
InletConditions in;
in.Tt1 = ein.Tt0; //You need to assign the value of ein.Tt0 to in.Tt1 here
std::cout << ein.Tt0 << endl;
std::cout << in.Tt1 << endl;
}
There are a lot of questions about static vs global here but I think my question is a bit different.
I want to know if there is a way to share a variable placed in a namespace across files the way static variables in a class can.
For example, I coded this:
//Foo.h
class Foo
{
public:
static int code;
static int times_two(int in_);
};
namespace bar
{
static int kode;
}
-
//Foo.cpp
int Foo::code = 0;
int Foo::times_two(int in_)
{
bar::kode++;
code++;
return 2*in_;
}
-
//main.cpp
int main()
{
cout << "Foo::code = " << Foo::code << endl;
for(int i=2; i < 6; i++)
{
cout << "2 x " << i << " = " << Foo::times_two(i) << endl;
cout << "Foo::code = " << Foo::code << endl;
cout << "bar::kode = " << bar::kode << endl;
if(i == 3)
{
bar::kode++;
}
}
}
All that yielded this for code and kode:
Foo::code = 1,2,3,4
bar::kode = 0,0,1,1
Once again, is there a way to share a variable placed in a namespace across files the way static variables in a class can? The reason I ask is because I thought I would be able to shield myself from confliciting global variables by using :: notation, and just found out I could not. And like any self-disrespecting programmer, I believe I am doing it wrong.
Yes:
//bar.h
namespace bar
{
extern int kode;
}
Outside of a class or struct, static has a whole different meaning. It gives a symbol internal linkage. So if you declare the same variable as static, you will actually get a different copy for all translation units, not a unique global.
Note that you'll need to initialize the variable once:
//bar.cpp
namespace bar
{
int kode = 1337;
}
devices.h file
#ifndef DEVICES_H
#define DEVICES_H
class malfunctionRecord
{
private:
int Num_Malfunction_Detection;
int Type_Malfunction;
int Last_Malfunction;
public:
malfunctionRecord();
void malfunction(int mlfn,int tm);
void display();
int getRecord(int*m,int*t);
};
class device
{
private:
char *Name;
malfunctionRecord malfunctionRec;
int Serial_Num;
int Value_Device;
public:
device(char*n,int sn);
~device();
void display();
void recordMalfunction(int m,int t);
int getMalfunctionRecord(int *m,int *t);
int amIThisDevice(char*n);
};
#endif
(this is my devices.cpp file)
#include<iostream>
#include "devices.h"
using namespace std;
malfunctionRecord::malfunctionRecord()
{
Num_Malfunction_Detection=0;
Last_Malfunction=0;
Type_Malfunction=='No_Malfunction';
}
void malfunctionRecord::malfunction(int mlfn,int tm)
{
Num_Malfunction_Detection=Num_Malfunction_Detection+mlfn;
Last_Malfunction=Last_Malfunction+tm;
}
void malfunctionRecord::display()
{
if (Num_Malfunction_Detection=0)
cout<<" the device has never malfunctioned";
else
cout<<"The device has malfunctioned"<<Num_Malfunction_Detection<<"times. the malfunction is type"<<Type_Malfunction<<" and last malfunction time is"<<Last_Malfunction<<endl;
}
int malfunctionRecord::getRecord(int*m,int*t)
{
cout<<"The device has malfunctioned"<<Num_Malfunction_Detection<<"times.";
Type_Malfunction=*m;
Last_Malfunction=*t;
}
/*int device::device(char*n,int sn)
{
}
void device::display()
{
}
void device::recordMalfunction(int m,int t)
{
}
int device::getMalfunctionRecord(int *m,int *t)
{
}
int device::amIThisDevice(char*n)
{
}
*/
(this is my main cpp file, given)
#include "definitions.h"
#include "devices.h"
#include <iostream>
using namespace std;
int main() {
malfunctionRecord m1, m2;
device d1("Turn Signal Lever", 195), d2("Accelerator", 247), *d3;
int c, m, t; // Temp variables to hold values retrieved from getRecord.
char ch; // Used to hold display until user presses enter.
// malfunctionReport tests.
cout << "Initially both m1 and m2 should have no malfunctions:\n\n";
m1.display();
cout << "\n";
m2.display();
cout << "\n";
// Set a malfunction in m1.
m1.malfunction(MALFUNCTION_UNDER_RANGE,10);
cout << "m1 should now have one malfunction with time 10 and under range.\n";
m1.display();
// Now add some malfunctions and verify that only the last is kept.
m1.malfunction(MALFUNCTION_OVER_RANGE,25);
cout << "\nm1 should now have two malfunctions, the last one with time 25 and over range.\n";
m1.display();
m1.malfunction(MALFUNCTION_STOPPED_WORKING,32);
cout << "\nm1 should now have three malfunctions, the last one with time 32 and stopped working.\n";
m1.display();
// Now test the retrieval function.
c = m1.getRecord(&m, &t);
cout << "\n\nValues returned from getRecord are " << c << ", " << m << ", and " << t << ".\n";
cout << "\nEnd of malfunctionReport tests.\n\n\n";
// Hold display so user has a chance to check results so far.
cout << "Press ENTR when ready to continue:";
ch = cin.get();
// device class tests.
cout << "\n\n\nBeginning tests for device class.\n";
cout << "Display original d1 and d2:\n\n";
d1.display();
cout << "\n";
d2.display();
cout << "\n\nTest the amIThisDevice function. \n";
if(d1.amIThisDevice("Turn Signal Lever")) cout << " First test on d1 passed.\n";
else cout << " First test on d1 failed.\n";
if(d1.amIThisDevice("Accelerator")==0) cout << " Second test on d1 passed.\n";
else cout << " Second test on d1 failed.\n";
cout << "\n\nNow test record and get malfunction function members.\n";
d1.recordMalfunction(MALFUNCTION_UNDER_RANGE,25);
cout << " Should see count equal 1 and under range malfunction at time 25:\n";
d1.display();
d1.recordMalfunction(MALFUNCTION_OVER_RANGE,50);
cout << "\n Should see count equal 2 and over range malfunction at time 50:\n";
d1.display();
d1.recordMalfunction(MALFUNCTION_STOPPED_WORKING,64);
cout << "\n Should see count equal 3 and stopped working malfunction at time 64:\n";
d1.display();
cout << "\n\nTry to retrieve malfunction report. Should see same values as above.\n";
c = d1.getMalfunctionRecord(&m,&t);
cout << "Values returned from getRecord are " << c << ", " << m << ", and " << t << ".\n";
// Test destructor. Create a new device and then delete it.
cout << "\n\nTesting create and destroy n object. If you don't see the";
cout << "\nend of tests message, there is something wrong with your destructor.\n\n";
d3 = new device("Temporary Device", 100);
d3->display();
delete d3;
cout << "\n\nEnd of tests for Program 3.\n";
return 0;
}
(this is my definition.h file)
#define NO_MALFUNCTION 20
#define MALFUNCTION_OVER_RANGE 21
#define MALFUNCTION_UNDER_RANGE 22
#define MALFUNCTION_STOPPED_WORKING 23
when I compile it, I keep getting these error:
g++ devices.cpp main.cpp -o a
devices.cpp:9:23: warning: character constant too long for its type
main.cpp: In function ‘int main()’:
main.cpp:11: warning: deprecated conversion from string constant to ‘char*’
main.cpp:11: warning: deprecated conversion from string constant to ‘char*’
main.cpp:53: warning: deprecated conversion from string constant to ‘char*’
main.cpp:56: warning: deprecated conversion from string constant to ‘char*’
main.cpp:76: warning: deprecated conversion from string constant to ‘char*’
Undefined symbols for architecture x86_64:
"device::device(char*, int)", referenced from:
_main in cc7F618W.o
"device::display()", referenced from:
_main in cc7F618W.o
"device::amIThisDevice(char*)", referenced from:
_main in cc7F618W.o
"device::recordMalfunction(int, int)", referenced from:
_main in cc7F618W.o
"device::getMalfunctionRecord(int*, int*)", referenced from:
_main in cc7F618W.o
"device::~device()", referenced from:
_main in cc7F618W.o
ld: symbol(s) not found for architecture x86_64
collect2: ld returned 1 exit status
can anyone tell me what's wrong with my codes? thanks!
You commented out a bunch of function definitions in devices.cpp (the five at the bottom). They're still in the header.
This is the linker complaining about you informing it of a symbol, and then not defining it.
Either define the functions or remove all the references to them.