In Java, you can write a constructor for an enum, e.g.
private MyEnum(String name, int val) {
...
}
And then you can write:
public enum MyEnum {
FIRST("A", 10), SECOND("B", 20), THIRD("C", 30);
private MyEnum(String name, int val) {
...
}
}
Is there any way you can do a similar thing for a C++ enum class?
No, C and C++ enums are just a bunch of constants grouped together. C++ enum classes are the same, but to access them you need to add the name of the enum class as a "namespace".
#pragma once
#include <afxwin.h>
#include "winnt.h"
#include "winuser.h"
/// <summary>
// define Style Constants
/// </summary>
enum IS_STYLES {
TB_TEXT_DEFAULT = 0,
TB_TEXT_DOUBLE = 1,
TB_TEXT_INTEGER = 2,
TB_TEXT_CAPTION_ABOVE = 4,
TB_TEXT_CAPTION_LEFT = 8
};
class CTextBox
{
public:
IS_STYLES mStyle;
CString mString;
CTextBox();
CTextBox(
CString string,
IS_STYLES style
);
};
#include "CTextBox.h"
CTextBox::CTextBox(
CString string,
IS_STYLES Style)
:mStyle(Style),mString(string) //init list
{
// body
}
#pragma once
#include <afxwin.h>
#include "CTextBox.h"
class CMainFrame : public CFrameWnd
{
private:
CTextBox mLength; // member objects
IS_STYLES mStyle;
protected:
public:
CObList myBoxes;
CMainFrame(); // Constructor
};
#include "CMainFrame.h"
#include "CTextBox.h"
CMainFrame::CMainFrame() // CMainFrame Constructor
{
/* Create a box that's comprised of an enum and string
CTextBox's constructor
*/
CTextBox box = CTextBox(IS_STYLES(TB_TEXT_DOUBLE|TB_TEXT_CAPTION_LEFT),
"Hello World");
myBoxes.AddHead((CObject*)box); // add box to a CObList collection.
};
Yes,you can! Follow below precisely:
declare the enum list (outside of the class)but in the same namespace and naturally give it a name.
in the .h file declare a class with a member value with a type of the defined enum, its name.
also in the .h file create a class overloaded Constructor who's signature includes having the enum type with a default value(also an enum), and must be at the end of the signature and Initialization list.
in the cpp, use the overloaded Constructor that includes the enum, here use the enum value of your choice, from the declared enum list.
also in the cpp, in the Class implementation
list, set the Class member's enum value to the enum declared your Constructor's signature(your chosen value).
Enjoy...
Not sure how you'd use "more" than 1 value in the Initialization List which would allow you to then be able to use bitwise and, and bitwise or decision making in your Derived / Instantiated Class.
Related
I have a private struct in my class Menu that contains menu item attributes. one of those attributes is a pointer to a function. It seems as though what I have written works when I forward declare functions outside the class, but having functions defined outside the class seems like very bad practice.
#pragma once
#include <string>
//forward declaration outside the class
void completelyRandom();//does not throw error
class Menu
{
private:
typedef void(*Menu_Processing_Function_Ptr)();
struct MenuItem
{
unsigned int number;
const char * text;
Menu_Processing_Function_Ptr p_processing_function;
};
MenuItem menu[] =
{
{1, "Completely random", completelyRandom}
};
public:
Menu();
~Menu();
};
And here is some code that throws the error but is closer to what I hope is possible:
#pragma once
#include <string>
class Menu
{
private:
typedef void(*Menu_Processing_Function_Ptr)();
struct MenuItem
{
unsigned int number;
const char * text;
Menu_Processing_Function_Ptr p_processing_function;
};
MenuItem menu[1] =
{
{1, "Completely random", completelyRandom}
};
public:
Menu();
//declaration within the class
void completelyRandom();//does throw error
~Menu();
};
I have tried moving the completelyRadom() declaration all around within the Menu scope, but get the error
a value of type "void (Menu::*)()" cannot be used to initialize an entity of type "Menu::Menu_Processing_Function_Ptr"
Is there a way I can forward declare the function that would be within best practices? Or should I regret my poor design choices and start all over?
"Non-static member functions (instance methods) have an implicit parameter (the this pointer) which is the pointer to the object it is operating on, so the type of the object must be included as part of the type of the function pointer. " - https://en.wikipedia.org/wiki/Function_pointer
check this code for an example:
#pragma once
#include <string>
class Menu
{
private:
//By specifying the class type for the pointer -> 'Menu::' in this case
// we no longer have to forward declare the functions
//outside of the class
typedef void(Menu::*Menu_Processing_Function_Ptr)();
struct MenuItem
{
unsigned int number;
const char * text;
Menu_Processing_Function_Ptr p_processing_function;
};
MenuItem menu[1] =
{
{1, "Completely random", completelyRandom}
};
public:
Menu();
void completelyRandom(); // no longer throws an error
};
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!
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,
};
};
Right now, my project has two classes and a main. Since the two classes inherit from each other, they are both using forward declarations. In the first object, right underneath the #include statement, I initialize two enums, before the class definition. I can use both enums just fine inside that class. However, if I try to use those enums in the other class, which inherits from the first one, I get an error saying the enum has not been declared. If I try to redefine the enum in the second class, I get a redefinition error.
I have even tried using a trick I just read about, and putting each enum in its own namespace; that didn't change anything.
Here's an example:
#ifndef CLASSONE_H
#define CLASSONE_H
namespace Player
{
enum Enum
{
One,
Two,
};
}
#endif
Then inside the second class, I attempt to use the enum declared earlier:
void AddPlayer(Player::Enum playerNumber);
and instead get an error saying 'Player' has not been declared.
I'm not sure what issue you are having without seeing your code, but this compiles:
enum OutsideEnum
{
OE_1,
OE_2,
};
namespace ns
{
enum NSEnum
{
NE_1,
NE_2,
};
}
class Base
{
public:
enum BaseEnum
{
BE_1,
BE_2,
};
void BaseFunc();
};
class Derived
{
public:
enum DerivedEnum
{
DE_1,
DE_2,
};
void DerivedFunc();
};
void Base::BaseFunc()
{
BaseEnum be = BE_1;
Derived::DerivedEnum de = Derived::DE_1;
OutsideEnum oe = OE_1;
ns::NEEnum ne = ns::NE_1;
}
void Derived::DerivedFunc()
{
Base::BaseEnum be = Base::BE_1;
DerivedEnum de = DE_1;
OutsideEnum oe = OE_1;
ns::NEEnum ne = ns::NE_1;
}
int main()
{
Base::BaseEnum be = Base::BE_1;
Derived::DerivedEnum de = Derived::DE_1;
OutsideEnum oe = OE_1;
ns::NEEnum ne = ns::NE_1;
}
Two things to watch for with enums defined inside a class definition:
Make sure it's declared public if you want it publicly available.
When referencing it from anywhere other than the class it's defined in, use the class name to qualify the name of the enum and the values.
EDIT:
Ok, the problem has nothing to do with enums, but rather order of inclusion, when you have a base class and a derived class, only the derived class needs to know about the base class:
Base class header:
#ifndef BASE_H
#define BASE_H
enum BaseEnum
{
};
class Base
{
};
#endif
Derived class header:
#ifndef DERIVED_H
#define DERIVED_H
#include "Base.h"
class Derived
{
void Func(BaseEnum be);
};
#endif