I have a basic class and header set up relating to an animal, I am trying to have a function which displays an animals current hunger level. Upon testing i have found the hunger level is not at the initial value i have set.
Monkey.cpp
#include "Monkey.hpp"
using namespace std;
Monkey::Monkey() {
}
unsigned int foodEaten = 0;
unsigned int foodIntake = 800;
unsigned int Monkey::hungerLevel() const {
return (makefoodIntake - foodEaten);
}
Monkey.hpp
#ifndef MONKEY_HPP
#define MONKEY_HPP
class Monkey : public Animal {
private:
unsigned int foodEaten;
unsigned int foodIntake;
public:
Monkey();
// Overridden to implement the monkey's hunger level
virtual unsigned int hungerLevel() const;
#endif /* end of include guard: MONKEY_HPP */
Why does this not return 800 initially?
Because you did not initialize the members of the class in your constructor.
You have some other variables, with the same name that are declared in the global scope.
However, because you have class members of the same name, the method uses the class members, and not the variables in the global scope.
You need to simply initialize the class members, instead of declaring global variables of the same name:
Monkey::Monkey() : foodEaten(0), foodIntake(800)
}
Both, foodEaten and foodIntake defined in the .cpp file are two variables in the global scope and not members of the class Monkey.
Initialize them in the header file as well:
class Monkey {
private:
unsigned int foodEaten{0};
unsigned int foodIntake{800};
// ...
};
Related
I have a problem when I'm using a static variable in my class constructor. I need to set two values equal to zero on the first line of initialization in the constructor, but I don't want to have them set to zero after the constructor is called again. These two values will be incremented. So after finding out about static variables I tried to use static variables in my constructor but errors showed.
So, what I want is for horPos and vertPos to be set to zero only once in the constructor and then incremented in the other function.
IOMovement.cpp:
#include "stdafx.h"
#include <iostream>
#include <Windows.h>
#include "IOMovement.h"
#include "rectangle.h"
#define W_KEY 0x57
#define S_KEY 0x53
#define A_KEY 0x41
#define D_KEY 0x44
#define R_KEY 0x52
void IOMovement::IO() {
rectangle player(15, 5);
if (GetAsyncKeyState(W_KEY)) {
system("CLS");
vertPos--;
player.rectangleDrawPos(horPos, vertPos);
}
if (GetAsyncKeyState(S_KEY)) {
system("CLS");
vertPos++;
std::cout << "Working\n";
player.rectangleDrawPos(horPos, vertPos);
}
if (GetAsyncKeyState(A_KEY)) {
system("CLS");
horPos--;
player.rectangleDrawPos(horPos, vertPos);
}
if (GetAsyncKeyState(D_KEY)) {
system("CLS");
horPos++;
player.rectangleDrawPos(horPos, vertPos);
}
}
void IOMovement::IOStartup() {
//Variable decleration
vertPos = 0;
horPos = 0;
//Functions
IO();
}
IOMovement.h:
#ifndef IOMOVEMENT_H
#define IOMOVEMENT_H
class IOMovement {
static int vertPos, horPos;
void IO();
public:
void IOStartup();
};
#endif
You do not need static for this use case. When you create an object, typically you call the constructor only once.
So, if you dont declare them as static and use the constructor to initialize them in the following way:
IOMovement::IOMovement() : vertPos(0), horPos(0)
{//Your constructor logic. }
Static variables are not initialized in constructor but maybe modified. They are initialized outside the class eg:
int IOMovement::vertPos = 0, horPos = 0;
And in des/constructor you can idec/ncrement them:
IOMovement::IOMovement(){
vertPos++;
horPos++;
}
IOMovement::~IOMovement(){
vertPos--;
horPos--;
}
Actually, when you're designing a class you can define static variables (members) inside the class, but you can't initialize them inside the class, where they're defined. If you want to initialize a static class variable (member), you can do it outside the class, at the rest of the source file by this way:
IOMovement.h
#ifndef IOMOVEMENT_H
#define IOMOVEMENT_H
class IOMovement {
// Here you define IOMovement class variables.
static int vertPos, horPos;
public:
// I think, you must put this function in the
// public function memebers of the class.
void IO();
void IOStartup();
};
#endif
IOMovement.cpp
#include "IOMovement.h"
...
// Here you initialize both static variables, at the source file
// before you use them.
IOMovement::vertPos = 0;
IOMovement::horPos = 0;
...
At the constructor you only can initialize non-static class member variables.
In this page is explained better how are initialized static members
of a class in c++:
All static data is initialized to zero when the first object is
created, if no other initialization is present. We can't put it in the
class definition but it can be initialized outside the class by
redeclaring the static variable, using the scope resolution operator
:: to identify which class it belongs to.
At this answer in Stack Overflow is a example:
They can't be initialised inside the class, but they can be
initialised outside the class, in a source file:
// inside the class
class Thing {
static string RE_ANY;
static string RE_ANY_RELUCTANT;
};
// in the source file
string Thing::RE_ANY = "([^\\n]*)";
string Thing::RE_ANY_RELUCTANT = "([^\\n]*?)";
In these pages you can get more information about static member of a c++ class:
Static Members of a C++ Class
C++ initialize static variables in class?
Constructors (C++)
I create a basic IBasic interface with a static field
class IBasic
{
public:
IBasic();
virtual ~IBasic();
static std::vector< std::vector<char> > Field;
};
from which the Inherit class is inherited:
class Inherit : public IBasic
{
public:
Inherit(int);
~Inherit();
void Foo();
};
The Inherit class makes some manipulations with Field static member in constructor/or member function.
In order to create an instance of the Inherit class, we need to explicitly declare a static field in the main.cpp before the main function:
#include "Basic.h"
#include "Inherit.h"
std::vector< std::vector<char> > IBasic::Field;
int main()
{
Inherit(10);
return 0;
}
The questions are:
In what namespace does the static method actually exists (global?)? Because I know that static field/function is not a class member in fact.
Is there another way to declare this static method, for example, in a
class file, inside a main function, or through creation unnamed namespace? Is it only one right variant?
How is right? What should be considered first of all?
A static member of a class is a member of its class (that's a tautology) and its class namespace (a class is a namespace). It is not a nember of any other namespace.
A non-const static data member of a class must be defined exactly once in a program, outside of any class, in the same namespace its class is defined in (a global namespace in your case). A header file is inappropriate place for such declaration. It is normally placed in an implementation .cpp file that goes together with the header file.
Having said that, an interface should not have any static data members, much less public ones. It is most likely a grave design error.
In what namespace does the static method actually exists (global?)? Because I know that static field/function is not a class member in fact.
It is declared in scope of the class. In fact the static variable is a class member, your assumption is wrong.
Is there another way to declare this static method, for example, in a class file, inside a main function, or through creation unnamed namespace? Is it only one right variant?
The usual way is to define it in the translation unit that contains the function definitions for the class.
How is right? What should be considered first of all?
There's no right or wrong way, but as mentioned definition in the same translation unit as the class function definitions is the usual way.
Here's an example usage of a static member without any inheritance.
SomeClass.h
#ifndef SOME_CLASS_H
#define SOME_CLASS_H
class SomeClass {
private:
int x;
public:
static SomeClass* const get(); // Needed For Using class to get this pointer
SomeClass();
int getX() const { return x; }
void setX( int val ) { x = val; }
};
#endif // SOME_CLASS_H
SomeClass.cpp
#include "SomeClass.h"
static SomeClass* s_pSomeClass = nullptr;
SomeClass::SomeClass() {
s_pSomeClass = this;
}
SomeClass* const SomeClass::get() {
if ( nullptr == s_pSomeClass ) {
// throw exception
}
return s_pSomeClass;
}
Another class using above class as a static member
OtherClass.h
#ifndef OTHER_CLASS_H
#define OTHER_CLASS_H
class SomeClass; // Forward Declaration
class OtherClass {
private:
static SomeClass* pSomeClass; // The Static Member to this class
int y;
public:
OtherClass();
int getY() const { return y; }
void setY( int val ) { y = val; }
void useSomeClassToSetY();
};
#endif // OTHER_CLASS_H
OtherClass.cpp
#include "OtherClass.h"
#include "SomeClass.h"
SomeClass* OtherClass::pSomeClass = nullptr;
OtherClass::OtherClass() {
if ( nullptr == pSomeClass ) {
pSomeClass = SomeClass::get();
}
}
void OtherClass::useSomeClassToSetY() {
// First Set X To Some Value:
pSomeClass->setX( 10 ); // Use of Static Member
y = pSomeClass->getX(); // Use of Static Member
}
Static members still belong to the class, but they have static storage.
I want to declare the length of an array member variable using a constant static variable of the class. If I do:
// A.h
#include <array>
using namespace std;
class A {
array<int,LENGTH> internalArray;
public:
const static int LENGTH;
};
// A.cpp
#include "A.h"
constexpr int A::LENGTH{10};
There is the error in A.h: "'LENGTH' was not declared in this scope", when declaring internalArray.
I find it weird because how come a class member variable, i.e. LENGTH, is out of scope inside the class? The only workaround I found was to move the initialization from A.cpp to A.h:
// A.h
#include <array>
using namespace std;
constexpr int LENGTH{10};
class A {
array<int,LENGTH> internalArray;
public:
const static int LENGTH;
};
But as I understand, first these are two different variables: the global namespace scope LENGTH and the class scope LENGTH. Also, declaring a variable in .h (outside class A) will create an independent LENGTH object in every translation unit where the header is included.
Is there a way to specify the length of the array with a static class-scoped variable?
Try this:
#include <array>
class A {
public:
static const size_t LENGTH = 12;
private:
std::array<int,LENGTH> internalArray;
};
int main(){
A a;
}
You can declare the value of LENGTH right in your class header, no need to have it be a separate global variable or for it to live in the cpp file.
Use the size_t type, since that is what the std::array template expects.
If that public/private arrangement is bad for you, know that you can include multiple public/private indicators in the class header.
/*
* CDummy.h
*/
#ifndef CDUMMY_H_
#define CDUMMY_H_
class CDummy {
public:
CDummy();
virtual ~CDummy();
};
#endif /* CDUMMY_H_ */
I've read that one should not declare class variables in header files. ist this right?
So I declare it in the cpp file below:
/*
* CDummy.cpp
*/
#include "CDummy.h"
static int counter = 0; //so here is my static counter. is this now private or public? how can i make it public, i cannot introduce a public block here.
CDummy::CDummy() {
counter++;
}
CDummy::~CDummy() {
counter--;
}
using this code i cannot access the classvariable from my main program....
thx
A "class variable" needs to belong to a class. So it has to be declared in the class definition. If the class definition is in a header file, then it follows that the class variable declaration must also be in a header file.
The class variable's definition should go in an implementation file, typically the one in which the class' members are defined. Here's a simplified example:
Foo.h
struct Foo
{
void foo() const;
static int FOO; // declaration
};
Foo.cpp
void Foo::foo() {}
int Foo::FOO = 42; // definition
What you have here:
static int counter = 0;
is a static variable that is not a static member of any class. It is only non-member static variable, static to the compilation unit of CDummy.cpp.
static int counter = 0; //so here is my static counter. is this now private or public? how can i make it public, i cannot introduce a public block here.
From the code I see counter is just a global static variables as it is not declated anywhere in your CDummy
Static variables should be public so that you could initialize them outside the class declaration. Your code should look like this to have it public:
class CDummy {
public:
static int count;
CDummy();
virtual ~CDummy();
};
// inside CDummy.cpp
int CDummy::count = 0;
Here you can read more about how to use static variables in class declaration.
Consider the following:
namespace MyNamespace{
class MyClass {
public:
// Public area
private:
// Private area
protected:
// Protected area
}; /* Class */
} /* Namespace */
And consider that I would like to define a constant which is specific for my class.
I usually do the following:
namespace MyNamespace{
// Constants
const int MYINT = 12;
const std::string MYSTR = std::string("Hello");
// Class definition
class MyClass {
public:
// Public area
private:
// Private area
protected:
// Protected area
}; /* Class */
} /* Namespace */
In this way I can get my variable in this way (somewhere in my code):
MyNamespace::MYINT;
MyNamespace::MYSTR;
Is this a good practice?
Considering that constants can be treated in several ways (for example numeric constants are often treated using enum), what is the best approach to define a constant (related to a class, but that can be also useful somewhere else)?
Thankyou
If you want the constants specific to the class and also want them to be useful somewhere else as you said, possibly outside the class, then define them as static member data in the public section of the class:
//.h file
class MyClass
{
public:
//constants declarations
static const int MYINT;
static const std::string MYSTR;
};
//.cpp file
//constants definitions
const int MyClass::MYINT = 12;
const std::string MyClass::MYSTR = std::string("Hello");
Usage (or access):
std::cout << MyClass::MYINT << std::endl;
std::cout << MyClass::MYSTR << std::endl;
Output:
12
Hello
Online Demo: http://www.ideone.com/2xJsy
You can also use enum if you want to define many integral constants and all of them are somehow related, for example this:
class shirt
{
public:
//constants declarations
enum shirt_size
{
small,
medium,
large,
extra_large
};
};
But if the integral constants are not related, then it wouldn't make much sense to define them as enum, in my opinion.
There is no "best" solution as of course that is a very subjective term.
Considering that you mention the constants being used somewhere else, we can say that they should be declared in either the protected (if they are to be used exclusively by derived classes) or more likely the public section of the class.
Constants that are not of integer type should be defined as static const members (but you will have to be careful of the order of static initialization if there are any other static objects that refer to these constants).
Constants of integer type can either be declared as static const int or as enums, as you already mention. The discriminating factor here is whether two or more constants can be logically grouped together.
For example, this is probably a good idea:
class MyClass {
public:
enum {
Color_Red,
Color_Green,
Color_Blue,
};
};
While this is not:
class MyClass {
public:
enum {
Color_Red,
Vehicle_Car,
};
};