Lately I was working on a simple game and the game structure required me to declare many types of objects... and to make working with functions easier, I made a parent class for all of the other classes. this is a part of the entire code(simplified):
int q=500;
struct ship
{
int x,y;
bool dec=0;
};
struct enemysol : public ship
{
int life=100,y=0,x;
bool dec=0;
void declare()
{
dec=1;
x=10+rand()%(getmaxx()-20);
life=100;
y=0;
}
};
int next(ship main[]) //finding next undeclared sol
{
int i=1;
while(main[i].dec)
{
i++;
if(i==q)
return -1;
}
return i;
}
The problem is that the next function will return i even if enemysol.dec=1
this code worked when I hadn't declared ship, but the project would have been very confusing and large if I didn't declared it..
You use the wrong way to initialize the member variables of your enemysol class.
When you write:
int life=100,y=0,x;
bool dec=0;
you declare new member variables, which have the same name than the x, y and dec that you already have in ship. So everytime you use x, y or dec in your enemysol class, you don't refer to the ship variables as these are hidden.
The right way of doing it would be something like:
struct enemysol : public ship
{
int life; // define only additional member variables not already in ship
enemysol() // constructor
: y(0), dec(false), life(100) // init members
{
}
void declare()
{
dec=1;
x=10+rand()%(getmaxx()-20);
life=100;
y=0;
}
};
Related
I'm making a simple game of catching the fruit, but I've been having troubles with the collision logic and/or using the variables from the classes.
class row
{
public:
int x,y;
void setpoint (int xi, int yi)
{
x=xi;
y=yi;
}
float DownSpeed = 5;
void down () {
y = y+DownSpeed;
if (y==1000) {
y=0;
}
}
};
class fruit:public row
{
public:
void draw()
{
setcolor(11);
circle(x,y,20);
}
};
Then I have other classes to create the catcher, like so:
class catcher
{
protected:
float moveSpeed = 5;
public:
float catchX, catchY;
void setpoint (int xi, int yi)
{
catchX=xi;
catchY=yi;
}
void MoveLeft () {
catchX = catchX - moveSpeed;}
void MoveRight () {
catchX = catchX + moveSpeed;}
};
class character:public catcher
{
public:
void draw()
{
setcolor(15);
circle(catchX,catchY,50);
}
};
How do I call the variables of both circles into creating a collision function? I'm sorry if the codes are messy and ineffective, I'm just starting out and I'm stuck. Thanks!
Since both sets of variables are in the public part of the class, you should be able to create a function independent of either class and should be able to access the variables as long as they are declared.
void CheckCollision(float x, float y, float catchX, float catchY)
{
If(y =< catchY + 5)
{
//y resets
}
}
You’d want to check if it’s within a certain x range too though. I hope this solves your problem.
Since all the functions and variables are public. return the values of x, catchX from the functions modifying them. use the draw functions after you have the modified values.
for example modify your down function like this
int down()
{
y = y+DownSpeed;
if (y==1000)
{
y=0;
}
return y;
}
Modify the other function like wise and you will end up having your x,y and catchX, catchY values. create you collison function with these values.
Please consider both the codes shown below. One uses a constructor to initialize the values and one does not.
Code#1
#include<iostream>
using namespace std;
class Rectangle
{
public:
int width;
int height;
};
int main()
{
Rectangle rect1{3,4};
cout<<"Width="<<rect1.width<<endl;
cout<<"Height="<<rect1.height<<endl;
return 0;
}
I get the output as,
Width=3
Height=4
Code#2
#include<iostream>
using namespace std;
class Rectangle
{
public:
int width;
int height;
Rectangle(int a,int b)
{
width=a;
height=b;
}
};
int main()
{
Rectangle rect1(3,4);
cout<<"Width="<<rect1.width<<endl;
cout<<"Height="<<rect1.height<<endl;
return 0;
}
I get the same output.
My question may be simple but, why bother using a constructor when I'm getting the same output in both the cases.
Thanks in advance
the answer is pretty simple, constructor initialize, other methods assign.
The difference may not seem very major, but consider this code.
#include<iostream>
using namespace std;
class Sample
{
private:
const int num;
public:
void setval(int i)
{
num = i;
}
int getVal()
{
return num;
}
};
int main()
{
Sample s;
s.setval(12);
cout<<s.getVal();
}
This code will give a compilation error saying that num is declared as const and we are trying to ASSIGN a value to num by making it equal to i.
Because const and references must be initialized just after declaration constructors do this Job by initializing them.
Also, make your class members private, it's a good practice and much more object oriented.
So the above code should be.
#include<iostream>
using namespace std;
class Sample
{
private:
const int num;
public:
Sample( int i):num(i){}
int getVal()
{
return num;
}
};
int main()
{
Sample s(12);
cout<<s.getVal();
}
For such simple data types it may well not matter, however there are many non plain-old-data types that benefit from or even require initialization to be at all useful.
Constructors have several benefits:
Constructors allow for a public API (encapsulation). In more complicated classes, internal data which the caller should not touch may need to be initialized.
class Foo
{
public:
Foo(int x) {
internal_data1 = some_computation1(x);
internal_data2 = some_computation2(x);
}
Some_Type3 some_method(int x)
{
return some_computation3(x, this->internal_data1, this->internal_data2);
}
private:
Some_Type1 internal_data1;
Some_Type2 internal_data2;
};
There are several C++ concepts involving constructors, such as DefaultConstructible and CopyConstructible. Constructors provide a common interface so generic code can instantiate objects of different types in a uniform way.
template<class T>
class Some_Generic
{
public:
Some_Generic(const T& t)
: internal_t(t) // Copy constructor used
{
// do work...
}
private:
T internal_t;
};
I want to do some conditional checks within a bool member function of a struct. How will my struct object struct1 know the bool member function has returned true, so that integers a & b can be used within the calc member function?
int main() {
vector<Point> pt;
pt.push_back(Point{ 1.5, 4.2 });
pt.push_back(Point{ 2.4, 3.1 });
doSth struct1;
bool tempbool = struct1.memfuncbool(pt); //error starts here!
if (tempbool) {int answer = struct1.calc(1);} //??
std::cout << answer;
return 0;
}
struct Point {
double _x;
double _y;
};
struct doSth {
int a, b; //data members
int calc(const int k) {
return (a + b)*k;
}
bool memfuncbool(const vector<Point> &pts) {
//does stuff...
a = var1; //var1 = 1
b = var2; //var2 = 2
return true;
}
}
There are two approaches: encapsulation for caller safety and pure code discipline. In the later you yourself make sure that the code you write is always aware of the latest result of memfuncbool and when and where a and b are set.
In the first you can add a flag in your struct that you set once memfuncbool is called and check in calc (and handle it appropriately.) In that case you should also make sure that the flag is cleared when initialising your struct - either via constructor or again code discipline (like always zero your structs).
An information hiding approach (C++) in the first sense would look like this:
class DoSth {
int a, b;
bool valid;
public:
DoSth() : valid(false) { }
bool isValid() const { return valid; }
/// returns calc if valid, otherwise 0
int calc(int k) const {
return isValid() ? (a + b) * k : 0;
}
void setSth(...) {
a = ...
b = ...
valid = true;
// instead of returning here the caller can check isValid() anytime
}
};
Your code has many issues that could easily be solved if you didn't try to do more than you know.
1 You're defining both Point and doSth structures AFTER the main function. So the main function has no way to know what your structures do. Normally you would use a header file to contain the declaration and the cpp file to contain the implementation, but since you're doing a small program you can just move the definitions of your structures to be above the main function. Alternatively you can declare your structures above main and implement them below, like this.
// Definition of struct Point
struct Point {
double _x;
double _y;
};
// Definition of struct doSth
struct doSth {
int a, b; //data members
// **Declaration** of doSth methods
int calc(const int k);
bool memfuncbool(const std::vector<Point> &pts);
};
int main() {
...
}
// Definition of calc method
int doSth::calc(const int k) {
...
}
// Definition of memfuncbool method
bool doSth::memfuncbool(const std::vector<Point> &pts) {
...
}
2 In the main function you're using a variable called answer in a scope that doesn't know such variable.
if (tempbool) {
int answer = struct1.calc(1);
}
std::cout << answer; // ERROR: answer is not a known variable
See, you're declaring a variable inside an if condition but using it outside. You have to declare the variable outside as well if you want to use it.
int answer = 0;
if ( tempbool ) {
answer = struct1.calc(1);
}
std::cout << answer << std::endl; // OK
OR
if ( tempbool ) {
int answer = strut1.calc(1);
std::cout << answer << std::endl;
}
else {
std::cout << "Invalid result!" << std::endl;
}
This is a fix to compile what you have done so far. But this is not a solution to your code design question.
3 Code Design
Although I suggested quick fixes to your code your actual problem has to do with how you design your classes and structure your code. I've showed you what you did wrong in your code, but your problem can be solved using a better structured approach.
While writing my answer Beyeler already answered this part for you, so check his answer.
EDIT
In your code you are probably doing
using namespace std;
But you've written both vector< Point > and std::cout. You should not use the using line, to begin with, to avoid name collisions and to help YOU know where this vector is coming from.
However, if you insist on using this line so you don't have to write std:: (and it's OK if you know what you're doing), don't go typing std:: on one thing and then omit it in another. Be consistent, either use it or don't.
I found three errors with your code:
"do" is a c++ keyword. You can't use it to name structs.
The parameter of the "memfuncbool" is missing its type. const& is not a type.
Missing semicolon after struct definition.
Also i supposed that var1, var2 and arg are well defined. If they are not even that is a error.
After correcting these errors maybe you can do something like-
if(tempbool) { /*statements*/ };
I have a problem with my code. I have two classes, Run and Robot, and I want an object of type Robot to change a private member of an object of type Run. To be specific, I want to increment the value of 'x' in the following code.
The following errors pop up:
error: 'getX' was not declared in this scope
error: 'getX' was not declared in this scope
I have pinpointed with an arrow (<---) the line where the error occurs. The following code is just a test, just to learn how to use the 'friend' keyword for a project.
#include <iostream>
#include <vector>
using namespace std;
class Robot;
class Run{
friend class Robot;
private:
int x;
vector<Robot*>robots;
public:
Run();
vector<Robot*>*getRobots();
void createRobot();
void movAll();
void setX(int);
int getX();
};
class Robot{
friend class Run;
public:
Robot();
void movingRobot();
};
Run::Run(){}
vector<Robot*>*Run::getRobots(){return &robots;}
void Run::createRobot(){getRobots()->push_back(new Robot);setX(1);}
void Run::movAll(){getRobots()->at(0)->movingRobot();}
int Run::getX(){return x;}
void Run::setX(int c){x=c;}
Robot::Robot(){}
void Robot::movingRobot(){setX(getX()+1);} <-------------------------
int main(){
Run Sim;
Sim.createRobot();
Sim.movAll();
}
Using the 'friend' keyword will definitely help on my project, so I am trying to understand how to use it.
You're just calling getX() and setX() as if they're methods of Robot. You need to call the function against an instance of Run, and in this case you don't need it to be a friend because getX() is public anyway.
That said, do you want each Robot to have an x value that you want to increment? In that case, you need it to be a member of Robot rather than Run.
If you want Run to have a single value of x that all instances of Robot can access and modify, then just make x static, then access it directly rather than calling the public methods, which don't require another class to be a friend anyway.
You called getX as if it were a function of the Robot-class. You need a run object to call it:
run.getX()
Ok you can remove the getX() function from The Robot class as it has no code body at present anyway, and for internal use the robot class can always utilise its X variable. Run doesn't need to have a friend class Robot, as Robot should not need to look into Run for anything, and as Run contains a vector of pointers to instances of Robot it can access any values of Robot instances by looking at the contents of its vector (for example myRunInstance.getRobots()[1]->getX() would return the x value of the 2nd robot in the vector of robots).
Now the getX function will have to vary a tad if it is to remain in the Run class: you will need to specify a way to make it gather the information of a specific instance of the Robot class, presumably from its vector of Robots. I have respecced your code above and added a small proof of concept set of code to the main, makes 10 robots moves them all using moveall, then sets Johnny5 to a special place (because he IS special:) Something along the lines of:
#include <iostream>
#include <vector>
using namespace std;
class Run;
class Robot{
friend class Run; // allows the Run class to access all the private data as if it were its own
private:
int x;
public:
Robot() {};
void setX(int newX) { x= newX; }
int getX() { return x; }
void movingRobot() { x+=1; }
};
class Run{
private:
vector<Robot*> robots;
public:
Run(){};
vector<Robot*> *getRobots() { return &robots; }
void createRobot() { robots.push_back(new Robot()); robots.back()->x =1; }
void movAll() { for (int i=0;i<robots.size();i++){ robots[i]->movingRobot();} }
int getX(int robotPosition){ return robots[robotPosition]->x; } //uses the friend status to read directly from Robot class instances x
void setX(int rpos, int xval){ robots[rpos]->setX(xval); }
};
int main()
{
Run *Sim = new Run();
for (int i =0; i< 10; i++)
{
Sim->createRobot();
Sim->setX(i,i); // uses the Run setX
std::cout << "Robot " << i << "(starting position): " << Sim->getRobots()->at(i)->getX() << std::endl;
}
Sim->movAll();
// lets move Johnny 5 to 55 as well...
(Sim->getRobots()->at(4))->setX(55); // uses the robot setx
for (int i=0; i< 10; i++)
{
std::cout << "Robot " << i << "(final position): " << Sim->getRobots()->at(i)->getX()<< std::endl;
}
return 0;
}
Source also viewable with sample output at Ideone
I have a constant value that never changes during run-time, but is impossible to know until run-time.
Is there a way to declare a constant (either as a member of a class or not) without defining it and also assign a computed value once (and only once) it is determined; or am I going to have to resort to a non-const declaration and use coding S & Ps (ALL_CAPS variables names, static declaration if in a class, etc.) to try and keep it from changing?
CLARIFICATION:
Though these are good answers, the real-world situation I have is more complicated:
The program has a main loop that continually runs between processing and rendering; the user can set required options and once they are set they will never change until the program is restart. An "Initialize" function is set up for anything that can be determined before the main loop, but values that are dependent on user interaction must be performed in the middle of the loop during the processing phase. (At the moment, persistent data storage techniques come to mind...)
Something like this?
const int x = calcConstant();
If it's a class member, then use the constructor initialisation list, as in Yuushi's answer.
You can define it in a struct or class and utilize an initialisation list:
#include <iostream>
struct has_const_member
{
const int x;
has_const_member(int x_)
: x(x_)
{ }
};
int main()
{
int foo = 0;
std::cin >> foo;
has_const_member h(foo);
std::cout << h.x << "\n";
return 0;
}
As a static or function-local variable:
const int x = calcConstant();
As a class member:
struct ConstContainer {
ConstContainer(int x) : x(x) {}
const int x;
};
Yes, you can make a private static singleton field with an initialization method and a gettor method. Here's an example of how to do it:
// In foo.h
class Foo
{
public:
// Caller must ensure that initializeGlobalValue
// was already called.
static int getGlobalValue() {
if (!initialized) {
... handle the error ...
}
return global_value;
}
static void initializeGlobalValue(...)
private:
static bool initialized;
static int global_value;
};
// In foo.cpp
bool Foo::initialized = false;
int Foo::global_value;
void Foo::initializeGlobalValue(...) {
if (initialized) {
...handle the error...
}
global_value = ...;
initialized = true;
}