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,
};
};
Related
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.
Suppose I have nested classes as follows defined in a header file:
class ClassA
{
private:
class ClassB
{
private:
int member_b;
public:
void function_name();
};
};
In order to give a definition to the function "function_name()" in an external .cpp file, I have to access it like this:
void ClassA::ClassB::function_name()
{
std::cout << member_b;
return;
}
For the sake of this example, please do not ask why I'm using nested classes; I have a reason for doing so in my actual project. However, my question is this; is it possible to somehow shorten the ClassA::ClassB::function_name() in the implementation file to something like short::function_name() while still keeping the classes nested? I don't think that typedefs or new namespace definitions can help me here, but maybe I'm wrong.
Qualified type names allow you to define a typedef to represent a qualified class name. You can then use the typedef with the :: (scope resolution) operator to refer to a nested class or class member, as shown in the following example:
class outside
{
public:
class nested
{
public:
static int x;
static int y;
int f();
int g();
};
};
int outside::nested::x = 5;
int outside::nested::f() { return 0; };
typedef outside::nested outnest; // define a typedef
int outnest::y = 10; // use typedef with ::
int outnest::g() { return 0; };
However, using a typedef to represent a nested class name hides information and may make the code harder to understand.
Source : https://www.ibm.com/support/knowledgecenter/en/SSPSQF_9.0.0/com.ibm.xlcpp111.aix.doc/language_ref/cplr061.html
Have you tried using aliases?
// C++11
using fmtfl = std::ios_base::fmtflags;
// C++03 equivalent:
// typedef std::ios_base::fmtflags fmtfl;
fmtfl fl_orig = std::cout.flags();
fmtfl fl_hex = (fl_orig & ~std::cout.basefield) | std::cout.showbase | std::cout.hex;
// ...
std::cout.flags(fl_hex);
Code source: https://msdn.microsoft.com/en-us/library/dn467695.aspx
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};
// ...
};
class Shapemaker
{
public:
static Shape * shapeCreate(CDrawView::shape sh);
};
My enum on my CDrawView class is
enum shape{line, rect, elli};
shape current_shape;
when i call Shapemaker::shapeCreate(current_shape) on I get error c2653CDrawView : is not a class or namespace name on shapemaker.h
This is probably the most plain thing to do:
class Shapemaker{
public:
enum Color { //your colors here }
};
class Otherclass{
void fun(Shapemaker::Color);
};
Now if your compiler does not recognize Shapemaker as a class name, that makes me think you didn't include its header file before declaring Otherclass.
If it's an enum member of the other class, then you can reference it as nameoftheClass::Color, but it'd have to be publicly-visible:
void function(nameoftheClass:Color input);
Say you have as follows:
class C {
public:
enum E {
HERP,
DERP
};
};
A function taking that enum would look like:
void foo(C::E e) {
// do stuff with e
}
It's all a matter of namespace in the end. Have a look at the answers to this question too, definitively you must not use the keyword enum in the function's parameter list, use directly the enum name with the appropriate namespace.
namespaces for enum types - best practices
i tried to pass the color variable enum, but it gives me a compile error saying that the "nameoftheclass" is not a class or namespace
You need to have a declaration placed before you use it, meaning you need proper header files:
MyClass.h
class MyClass {
public:
enum Color {
Red,
Green,
Blue
};
};
MyOtherClass.h
#include "MyClass.h" // This is required.
// Now you can use MyClass::Color freely.
I have a class in which I have an enumeration, defined like this:
class X
{
public:
enum Direction {DIR_LEFT, DIR_RIGHT};
};
Now I want this enumeration to be reused in another class, like this:
class Y
{
public:
typedef X::Direction Direction;
};
As expected, using Y::Direction works correctly, e.g.:
void myFunction (Y::Direction dir)
{
}
But the values within the enumeration does not seem to be 'copied' together with the typedef. If I write the following, I get compilation errors:
myFunction (Y::DIR_LEFT);
Instead, I have to refer to the original place of the enumeration again, like this:
myFunction (X::DIR_LEFT);
Which defeats my purpose of typdefing the enumeration.
The only solution I see is to move the enumeration out of class X, and putting it in another class (e.g. MyEnums), so it can be reused by X and Y (although they should still use MyEnums::DIR_LEFT and MyEnums::DIR_RIGHT), but at least the code does not depend on class X anymore.
Why are the enumeration values itself no exposed via the typedef?
Are there any other patterns to manage enumerations in different classes?
Unfortunately C++ doesn't introduce a new scope with an enum although C++0x is improving things.
Practically this means that you can't typedef an enum and get the enumerated values as well.
What you can do is use a nested struct with the name you want for the enum and typedef THAT.
class X
{
public:
struct Direction { enum EnumType {LEFT, RIGHT}; };
};
class Y
{
public:
typedef X::Direction Direction;
};
Now you can do:
myFunction (Y::Direction::LEFT);
The purpose of the nested struct is to create a "fake" scope to holld both the enum name and its values.
Here is my understanding of how enums work in C++. (Or at least my observed behaviour of enums in Microsoft Visual C++.)
The enum keyword does not create a scope the same way that classes do.
The full name then for your enum 'Direction', is X::Direction. The values within that enum are still part of the class scope, so they are X::DIR_LEFT and X::DIR_RIGHT.
When you typedef the enum in another class, this does not change the scope of the values of the enum.
I suggest you put the enum inside a namespace in a header file if you want to share it in multiple locations.
If you want the enum values to be members of both classes, the
solution is to define a separate class with the enum, and
inherit from it, e.g.:
class MyEnums
{
protected:
~MyEnums() {} // Prevent delete through pointer to this class
public:
enum Direction
{
DIR_LEFT,
DIR_RIGHT
};
};
class X : public MyEnums
{
// ...
};
class Y : public MyEnums
{
// ...
};
Users will see X::Direction, X::DIR_LEFT and Y::Direction,
Y::DIR_LEFT. Of course, they'll still be able to pass
a Y::DIR_LEFT to a function expecting an X::Direction; to
prevent that, make MyEnums a template, with the derived class as
the template argument.
Anything shared by more than one class should be factored outside of the classes and perhaps into a parent class.
direction.hpp:
#ifndef DIRECTION_HPP
enum Direction {DIR_LEFT, DIR_RIGHT};
#endif
x.hpp:
#ifndef X_HPP
#include "direction.hpp"
class X
{
Direction dir;
};
#endif // X_HPP
y.hpp
#ifndef Y_HPP
#include "direction.hpp"
class Y
{
Direction dir;
};
#endif // Y_HPP
If the original declaration:
class X
{
public:
enum Direction {DIR_LEFT, DIR_RIGHT};
};
is embedded in a large legacy code-base, then we might want a solution that does not change any existing uses of X::Direction. In that case, the rather ugly:
class Y
{
public:
typedef enum X::Direction Direction;
static const enum X::Direction DIR_LEFT = X:DIR_LEFT;
static const enum X::Direction DIR_RIGHT = X:DIR_RIGHT;
}
works...
Definitely not recommended for new code, however!