I am trying to define in a .cpp file an attribute which should be an array of pointers to member functions of a class named Hand.
Both the array and the functions are members of Hand and the array is static(please correct me if it should not).
This is what I reached:
static bool Hand::*(Hand::hfunctions)[] ()=
{&Hand::has_sflush,&Hand::has_poker,&Hand::has_full,&Hand::has_flush,
&Hand::has_straight,&Hand::has_trio,&Hand::has_2pair,&Hand::has_pair};
I get this error: hand.cpp:96:42: error: declaration of ‘hfunctions’ as array of functions.
I guess the type definition is worng so I need to know how can I make the definition right
The syntax is a rather convoluted one:
class Hand
{
bool has_sflush();
static bool (Hand::*hfunctions[])();
...
};
bool (Hand::*Hand::hfunctions[])() = {&Hand::has_sflush, ...};
A way to get to this is by gradually increasing complexity, using cdecl.org to check yourself at each step:
int (*hFunctions)()
declare hFunctions as pointer to function returning int
int (Hand::*hFunctions)()
declare hFunctions as pointer to member of class Hand function returning int
Warning: Unsupported in C -- 'pointer to member of class'
int (Hand::*hFunctions[])()
declare hFunctions as array of pointer to member of class Hand function returning int
Warning: Unsupported in C -- 'pointer to member of class'
Now replace int by bool (sadly, cdecl.org doesn't understand bool); so you get the syntax of the declaration.
For the definition, replace hFunctions by Hand::hFunctions, and add the initialization part, like you did.
Both the array and the functions are members of Hand and the array is static(please correct me if it should not).
If I understand correctly what you are asking, you should not. You should abstract the operation as a base class, specialize it and hold the array as an array of pointers to the base class:
struct Match // need a better name
{
virtual bool matches() = 0;
virtual ~Match() = default;
};
struct MatchSFlush: public Match { ... };
class Hand
{
static std::vector<std::unique_ptr<Match>> matches;
};
If you have non static member functions with no arguments and returning bool you should write something like
typedef bool (Hand::*hfunction_non_static)();
hfunction_non_static f_non_static [] =
{
&Hand::has_sflush,
&Hand::has_poker,
.......
};
Hand h;
(h.*f_non_static[0])();
If you have static functions you should write something like
typedef bool (*hfunction_static)();
hfunction_static f_static [] = {&Hand::has_sflush, ....};
f_static[0]();
Related
In a file named maze.hpp (a header file) I have the following:
class Maze
{
public:
Maze(int size);
~Maze() {}
void step();
private:
int exitRow;
};
In another file named maze.cpp I have the following:
void step(){
this.exitRow = 3;
}
int main(){
Maze maze(4);
maze.step();
}
This gives an error: invalid use of 'this' outside of a non-static member function
step is a member function of Maze. How can I access the data members of an instance of Maze from within one of its member functions?
When you define a function outside of the class declaration, you are required to provide the class name like this:
void Maze::step(){
exitRow = 3;
}
The compiler has no other way of knowing where the method that you're defining belongs.
Note that there is no need to use this when referring to members from a member function. this is still available and technically writing something like the following is valid: this->exitRow = 3;, but unnecessary. Also, this is a pointer (hence the usage of operator -> rather than .).
The lines
void step(){
this.exitRow = 3;
}
define a global function, not a member function of Maze. Also, this.exitRow is the wrong syntax. You need:
void Maze::step(){
this->exitRow = 3;
}
Your function definition should be:
void Maze::step()
{
}
The way it is now, it just defines a free standing function that does not belong to any class.
Also, this is a pointer so you need to access members by dereferencing it using ->. And it is good to note that you do not need to use this->exitRow to refer exitRow, merely mentioning exitRow inside the member function will serve the same purpose.
I would to initialize a const int member (numGrids) of my class TestCase when I construct a TestCase. It needs to be const (I think) because it defines the elements of another array member of the classwhich I would also like to initialize when I create a TestCase. The code is shown below:
/////////////////////////////////////////////////////////////////////////////////////
//TestCase.h
class TestCase
{
protected:
const int numGrids;
Grid meshes[numGrids];
public:
TestCase(const int);
};
/////////////////////////////////////////////////////////////////////////////////////
//TestCases.cpp
TestCase::TestCase(const int numGridsSpec)
{
numGrids = numGridsSpec;
Grid grids[numGrids];
}
I cannot seem to initialize the const member of my class. I need that member to be constant because it defines the array size of meshes. I get the following errors:
[ 12%] Building CXX object sources/CMakeFiles/GridRefinementStudy.dir/TestCase.cpp.o
In file included from /home/omar/Documents/Programming/C++/FCFD/Current/sources/TestCase.cpp:16:0:
/home/omar/Documents/Programming/C++/FCFD/Current/sources/TestCase.h:5:12: error: invalid use of non-static data member ‘TestCase::numGrids’
/home/omar/Documents/Programming/C++/FCFD/Current/sources/TestCase.h:6:14: error: from this location
/home/omar/Documents/Programming/C++/FCFD/Current/sources/TestCase.h:6:22: error: array bound is not an integer constant before ‘]’ token
/home/omar/Documents/Programming/C++/FCFD/Current/sources/TestCase.cpp: In constructor ‘TestCase::TestCase(int)’:
/home/omar/Documents/Programming/C++/FCFD/Current/sources/TestCase.cpp:25:1: error: uninitialized member ‘TestCase::numGrids’ with ‘const’ type ‘const int’ [-fpermissive]
/home/omar/Documents/Programming/C++/FCFD/Current/sources/TestCase.cpp:28:13: error: assignment of read-only member ‘TestCase::numGrids’
/home/omar/Documents/Programming/C++/FCFD/Current/sources/TestCase.cpp:29:21: error: no matching function for call to ‘Grid::Grid()’
/home/omar/Documents/Programming/C++/FCFD/Current/sources/TestCase.cpp:29:21: note: candidates are:
/home/omar/Documents/Programming/C++/FCFD/Current/sources/Grid.h:13:2: note: Grid::Grid(int, int, double, double)
/home/omar/Documents/Programming/C++/FCFD/Current/sources/Grid.h:13:2: note: candidate expects 4 arguments, 0 provided
/home/omar/Documents/Programming/C++/FCFD/Current/sources/Grid.h:1:7: note: Grid::Grid(const Grid&)
/home/omar/Documents/Programming/C++/FCFD/Current/sources/Grid.h:1:7: note: candidate expects 1 argument, 0 provided
make[2]: *** [sources/CMakeFiles/GridRefinementStudy.dir/TestCase.cpp.o] Error 1
make[1]: *** [sources/CMakeFiles/GridRefinementStudy.dir/all] Error 2
make: *** [all] Error 2
You may not do such a way. The size of the array shall be known at compile time. In fact you are trying to get a variable length array. C++ does not have such a feature.
Take into account that if the sizes of the array are different for two objects then the classes that define them are different types. They have different data members that is arrays with different sizes. The size of a class shall be the same for each object of that class.
I would suggest to use standard container std::dynarray if the compiler supports it or
std::vector
On the other hand you could define your class as a template class. For example
template <size_t numGrids>
class TestCase {
protected:
Grid meshes[numGrids];
//...
or even as
template <size_t numGrids>
class TestCase {
protected:
std::array<Grid, numGrids> meshes;
//...
I think that using a template class is the best approach in your case.
In pre-C++11, there are four ways of initializing a member:
If the member is static, const and has an integral type,
it can be initialized directly in the class definition. In this
case, the member is a "integral constant expression", and can be
used anywhere the compiler requires such (e.g. array dimensions,
template argument, etc.).
If the member is static, it must be initialized in its
definition. If the member is also const, it is a constant
expression in the translation unit which contains the
definition, after the definition.
Any member can be initialized in the initializer list, and
typically, all should be (but there are exceptions). Non-static
const members must be initialized here (but non-static const
members are not constant expressions, and cannot be used as
such).
Finally, non-const members can be "initialized" in the
constructor body. Formally, this is assignment, not initialization, and if
the member type has a user defined constructor, it will still be
initialized (using the default constructor) in the
initialization list. For primitive types, the member remains
uninitialized if it isn't mentionned in the initializer list,
until it is first assigned.
In your case, it would appear that you want an array whose size
is defined by a parameter to the constructor. This is not
possible; the size of an array must be an integral constant
expression. If the size should always be the same, then you can
use a static const int to define it:
class TestClass
{
static int const numGrids = 25;
Grid meshes[numGrids];
// ...
};
Otherwise, you'll have to use:
class TestClass
{
std::vector<Grid> meshes;
public:
TestClass( int size ) : meshes( size ) {}
};
This might be the better solution anyway.
First of all since numGrids is const in the class declaration, you can only initialize it through initialization list.
TestCase::TestCase(const int numGridsSpec)
:numGrids(numGridsSpec) // this is the initialization list
{
...
}
This is simply because a constant variable can only be set to a value once and can not be modified 'legally' thereafter, compilers normally would not allow you to proceed avoiding unexpected consequences in this case.
There's a mistake in your code. The array size is dynamic (a variable). You can't use a variable to declare an array size at compile time. Use some constants with real value.
To Answer your question
Initializer list is used to init the data for a const. Something as follows.
class TestCase {
protected:
const int numGrids;
public:
TestCase(const int x) : numGrids(x)
{
}
};
Solution for your problem
class TestCase {
protected:
const int numGrids;
Grid* pMeshes;
public:
TestCase(const int x) : numGrids(x)
{
pMeshes = new Grid[x];
}
~TestCase() : numGrids(x)
{
delete []pMeshes; // release allocated memory in destructor
}
};
int main(int argc, char* argv[])
{
TestCase t(10);
return 0;
}
If your compiler supports c++11, you could simply do:
class TestCase
{
protected:
const int numGrids = 25;
Grid meshes[numGrids];
public:
TestCase(const int);
};
I am having difficulty getting my head around how to pass a class member function to a subclass (not derived).
My top level class is like this:
class CTop
{
public:
CTop();
int func1(void);
private:
CFnList* _funcList;
};
CTop::CTop():
_funcList(0)
{
_funcList = new CFnList();
_funcList->addFnPtrToList(0, &CTop::func1);
}
int CTop::func1(void)
{
// Does some stuff...
}
My function list class is like this:
class CFnList
{
public:
// Public functions
CFnList();
void addFnPtrToList(int index, int (*fn)(void));
private:
// Fn pointer list
typedef struct
{
int index;
int (*fn) (void);
}fn_list_t;
// function pointer list
QVector<fn_list_t> _fn_list;
};
So basically here I have an instance of class CTop and one of its members is a pointer to a class CFnList. CFnList pointer is instantiated in the constructor of CTop. Then I want to pass in a pointer to one of CTop's member functions to CFnList by calling the following line:
"_funcList->addFnPtrToList(0, &CTop::func1);"
I get issue (quite rightly) that addFnPtrToList does not take the parameters (int, (CTop::*)()). So the compiler knows this function is a certain member function and not just a generic (maybe static) function.
Is there a way to pass the a pointer to the member function into the sub-class? In my case I want the sub-class to be able to call this function. I am thinking I probably have to make static member functions or something, but the syntax is eluding me on how to do this.
All help / advise appreciated.
Fodder
CTop::func1 is a member function. &CTop::func1 is NOT a function pointer, it is a pointer to member (function). Those can not be mixed either in storing or calling. it is not compatible with int (*fn)(void), as the latter takes no arguments and the former requires an object that is passed as the hidden this.
For these reasons you can't have a simple but uniform facility. You either can go with simple function pointers, or pairs of PTM+object pointer, or use wrappers -- handmade or stock like boost::function fueled by boost::bind. If you have C++11 or TR1 you can use the std:: equivalents of the latter.
A declaration in the form:
int (*fn)(void)
cannot point to a member function. It can only point to a free function. Philispophically, this is because the calling conventions for member functions are different then that for free functions. Consider for example the need for a this pointer in the context of a member function call.
The syntax for declaring a pointer-to-member-function is like this:
int (CTop::*fn)(void)
There is an entire section in the C++ FAQ dedicated to member function pointers. Check it out.
You are passing the member function as if it were a regular function. That fails to include the 'this' reference to the class. In order to pass member functions, you have to be able to re-reference it from the original 'this'. Take a look at the following, instead.
typedef void (CTop::*OBJFNC)(args);
_funcList = new CFnList();
_funcList->addFnPtrToList(0, this, &CTop::func1);
void addFnPtrToList(int index, CTop* pobj, OBJFNC pfnc)
{ ... Store both ...
}
Now elsewhere you can execute it with the following.
(pobj->*pfnc)(args);
Here is the final solution, it uses a mixture of passing the instance of the object CTop and usage of template class for CFnList:
My top level class is like this (more or less the same except for the declaration of _funcList to includes the class type and to pass in the "this" to the constructor:
class CTop
{
public:
CTop();
int func1(void);
private:
CFnList<CTop>* _funcList;
};
CTop::CTop():
_funcList(0)
{
_funcList = new CFnList(this);
_funcList->addFnPtrToList(0, &CTop::func1);
}
int CTop::func1(void)
{
// Does some stuff...
}
My function list class is like this:
template<class T>
class CFnList
{
public:
// Public functions
CFnList(T *parent);
void addFnPtrToList(int index, int (T::*fn)(void));
private:
// Pointer to the parent (or owner is perhaps more correct)
T* _parent;
// Fn pointer list
typedef struct
{
int index;
int (T::*fn) (void);
}fn_list_t;
// function pointer list
QVector<fn_list_t> _fn_list;
};
// Constructor
template <class T>
CFnList<T>::CFnList(T *parent) :
_parent(parent),
_fn_list(0)
{
}
// addFnPtrToList:
template <class T>
void CFnList<T>::addFnPtrToList(int index, int (T::*fn)(void))
{
_fn_list.append((fn_list_t){index, fn});
}
So the major changes are:
1. Pass the CTop type in by using changing CFnList into a template.
2. Pass in the instance of the object CTop (so that the pointer to the function can be called) by passing "this" into the constructor and then template class stores it as a pointer to the given template type.... vio-la!...easy :o
Thanks to all who contributed :))
I am new to function pointers and I would like your help.
I am having a method:
int test3(int i)
{
return i;
}
Then in another method(not main) I do:
int (*pTest3)(int) = test3;
From the examples that I have read this seems ok.
However, I get a compile time error:
testFile.cpp:277:25: error: argument of type ‘int
({anonymous}::CheckingConsumer::)(int)’ does not match ‘int (*)(int)’
I do not understand what is wrong. Any help would be appreciated.
Thanks a lot.
Your test3 is a member function of a struct or a class. Class member functions have a hidden this parameter passed into them and so cannot be used with plain function pointers. You need to either declare the function as static or move it outside the struct/class, so that it no longer has a hidden this parameter, or use a class method pointer instead of a function pointer:
// static class method:
class X
{
static int test3(int i)
{
...
}
};
// Non-class method, at global scope
int test3(int i)
{
...
}
// Class method pointer
class X
{
int test3(int i)
{
...
}
};
// Create the method pointer
int (X::*pTest3) = &X::test3;
X *obj;
// Call the method pointer on an object
(obj ->* pTest3)(42);
Your method test3 seems to be an instance method. Later on you define pTest3 as function pointer, not as member function pointer.
Main difference between simple pointers and member pointers is that using the member pointer requires an instance of the object. An instance of the object tells what object should be processed and the value of the pointer tells what data field of the object should be used or what member function should be called. Value of the member pointer is conceptually equivalent to the offset from the beginning of the object to its member.
Declaring the member pointer using typedef:
typedef int (SomeClass::*MyMethodPtr)(int i);
MyMethodPtr ptr3 = SomeClass::test3;
Now using this pointer:
class SomeClass *pab = &ab;
int ret_value = (pab->*ptr3)(4);
Note that the instance of the class is used. There is other important point about the member pointers. They are implemented as structs that contain inside from 2 to 5 simple pointers and offsets depending on the compiler and other aspects like multiple inheritance, presence of vitrual base classes, etc.
I'm developing a game which is based around the user controlling a ball which moves between areas on the screen. The 'map' for the screen is defined in the file ThreeDCubeGame.cpp:
char m_acMapData[MAP_WIDTH][MAP_HEIGHT];
The ThreeDCubeGame.cpp handles most of the stuff to do with the map, but the player (and keyboard input) is controlled by ThreeDCubePlayer.cpp. When a player moves into a new map cell, the game will have to check the contents of that cell and act accordingly. This function in ThreeDCubeGame.cpp is what I am trying to use:
inline char GetMapEntry( int iMapX, int iMapY ) { return m_acMapData[iMapX][iMapY]; }
So, in order to check whether the player is allowed to move into a map cell I use this function call from ThreeDCubePlayer.cpp:
if (ThreeDCubeGame::GetMapEntry(m_iMapX+MAP_OFF_X, m_iMapY+MAP_OFF_Y) == ' ')
{
// do stuff
}
But, when I compile this, I get the warning "error C2352: 'ThreeDCubeGame::GetMapEntry' : illegal call of non-static member function". Is this something to do with the scope of the variables? Is it fixable without redesigning all the code?
class A {
int i;
public:
A(): i(0) {}
int get() const { return i; }
};
int main() {
A a;
a.get(); // works
A::get(); // error C2352
}
There's no object to call the function with.
GetMapEntry is not static so you can't call it without an object of the type ThreeDCubeGame.
Alternatives:
-Make GetMapEntry static: static inline char GetMapEntry
-Create an instance of ThreeDCubeGame and do instance.GetMapEntry(
ThreeDCubeGame is a class, not an instance, thus you can only use it to access static members (that is, member function with the keyword static)
You have to instantiate an object of this class to use non-static members
ThreeDCubeGame map;
...
map.GetMapEntry(iMapX, iMapY).
You are trying to call a class method. Is that what you intend? Or do you mean for GetMapEntry to be an instance method? If it's a class method, it needs to be marked static. If it's an instance method, you need to call it with an instance of ThreeDCubeGame. Also, is GetMapEntry even a member of a class?
The error indicates that your are calling the GetMapEntry function as a static one whereas you have declare it as a member function. You need to:
call it via an instance of ThreeDCubeGame: threedcubegameinstance.GetMapEntry(),
declare the GetMapEntry function as static (add a static before inline and make m_acMapData static too).
You're missing the "static" keyword.
// .h
class Playfield
{
public:
static char GetTile( int x, int y );
// static on a method means no 'this' is involved
};
// .cpp
static char tiles[10][10] = {};
// static on vars in .cpp prevents access from outside this .cpp
char Playfield::GetTile( int x, int y )
{
// handle invalid args
// return tile
return tiles[x][y];
}
There's other options if you want only one unique playfield:
You can make Playfield a singleton, turn it into a namespace or use global functions.
The result is the same from the caller's point of view.
On a side note:
Since all of these use a static and/or global variable it's inherently not thread-safe.
If you require multiple playfields and/or want to play safe with multi-threadding and/or want to absolutely do it in an OOP fashion, you will need an instance of Playfield to call the function on (the 'this' pointer):
class Playfield
{
public:
char GetTile( int x, int y ) const { return this->tiles[x][y]; }
// you can omit 'this->', but it's inherently present because
// the method is not marked as static
public:
Playfield()
{ /*you will have to initialize 'this->tiles' here because
you cannot use the struct initializer '= {}' on member vars*/ }
private:
char tiles[10][10];
};
The calling code would use Playfield like this:
void main()
{
// static version
char tile11 = Playfield::GetTile( 1, 1 );
// non-static version
Playfield myPlayfield;
char tile12 = myPlayfield.GetTile( 1, 2 );
}
It can be useful to have a class containing a collection of functions, without any data members, if you don't want to expose the helper-functions.
Otherwise it would be more practical to use a namespace to collect these functions in.
Example:
class Solvers
{
public:
void solve_a(std::vector<int> data);
void solve_b(std::vector<int> data, int value);
private:
int helper_a(int a, int b);
}
But a class needs to be initialised before use.
The simplest way to make these functions usable would be to mark them static in the class:
static void solve_a(std::vector<int> data);
Then the member-functions can be used as:
Solver::solve_a(my_vector);
Another way would be to initialise the class before using:
Solver solver;
solver.solve_a(my_vector);
And the third method, not mentioned before, is by default initialising it during use:
Solver().solve_a(my_vector);