I wrote a simple class that performs basic arithmetic operations using a method that receives an index and two values to compute.
The index indicates which operation to perform in a table that contains pointers to functions.
Here is my code:
#include <iostream>
using namespace std;
class TArith
{
public:
static const int DIV_FACTOR = 1000;
typedef int (TArith::*TArithActionFunc)(int,int);
struct TAction
{
enum Values
{
Add,
Sub,
count,
};
};
int action(TAction::Values a_actionIdx, int a_A, int a_B)
{
return ( this->*m_actionFcns[a_actionIdx] )(a_A,a_B);
}
private:
int add(int a_A, int a_B)
{
return a_A + a_B ;
}
int sub(int a_A, int a_B)
{
return a_A - a_B ;
}
static TArithActionFunc m_actionFcns[TAction::count];
int m_a;
int m_b;
};
TArith:: TArithActionFunc TArith:: m_actionFcns[TAction::count] = {
TArith::add,
TArith::sub
};
void main(void)
{
TArith arithObj;
int a=100;
int b=50;
for(int i = 0 ; i <TArith::TAction::count ; ++i)
{
cout<<arithObj.action( (TArith::TAction::Values)i,a,b )<<endl;
}
cout<<endl;
}
Compiler says:
'TArith::add': function call missing argument list; use '&TArith::add' to create a pointer to member
'TArith::sub': function call missing argument list; use '&TArith::sub' to create a pointer to member
why do I need to use the & symbol?
TArith:: TArithActionFunc TArith:: m_actionFcns[TAction::count] = {
TArith::add,
TArith::sub,
TArith::mul,
TArith::div
};
Correct syntax for a pointer to a member function f of a class C is &C::f. You're missing the leading &.
Try:
TArith:: TArithActionFunc TArith:: m_actionFcns[TAction::count] = {
&TArith::add,
&TArith::sub,
&TArith::mul,
&TArith::div
};
Related
I have an assignment for university which requires me to access the vtable of a class. I need to write a function (here called pb) which takes a pointer to an object as an argument as well as an integer, and then just prints the output of the methods of the class. I have managed to access the first function, but I don't know how to access the second function. Here's the code I have so far:
typedef int(*firstFun)();
typedef int(*secondFun)(int);
class B {
public:
virtual int __cdecl first() = 0;
virtual int __cdecl second(int) = 0;
};
class D : public B {
public:
virtual int __cdecl first() { return 42; }
virtual int __cdecl second(int x) {
return first() + x; }
};
void pb(B* object, int x) {
unsigned int adressVTable = *(unsigned int*)object;
unsigned int adressVTable2; //yet unknown
firstFun bFirst = (firstFun)(*(unsigned int*)(adressVTable));
secondFun bSecond = (secondFun)(*(unsigned int*)(int)(adressVTable2));
int f=bFirst();
int s=bSecond(x);
printf("First: %d, second: %d", f, s);
}
In conclusion, how to get bSecond to work for second(int) like bFirst works for first()?
The vTable is just an array of function pointers, so just an array of pointers. If the target process is x86 then just add 0x4 to the address of the first pointer and you will get the second pointer in the vtable. If the target process is x64, add 0x8 because that's the size of a pointer on that architecture.
Secondly, you're defining these as cdecl function which isn't going to work how you've planned. Virtual functions / member functions are __thiscall, which require the this pointer to be passed in ECX. So you need to typedef the function pointers correctly and pass the thisptr as the first argument.
Tested working:
typedef int(__thiscall *firstFun)(void* thisptr);
typedef int(__thiscall *secondFun)(void* thisptr, int);
class B
{
public:
virtual int first() = 0;
virtual int second(int) = 0;
};
class D : public B
{
public:
virtual int first() { return 42; }
virtual int second(int x)
{
return first() + x;
}
};
void pb(B* object, int x)
{
unsigned int adressVTable = *(unsigned int*)object;
unsigned int adressVTable2 = adressVTable + 0x4;
firstFun bFirst = (firstFun)(*(unsigned int*)(adressVTable));
secondFun bSecond = (secondFun)(*(unsigned int*)(adressVTable2));
int f = bFirst(object);
int s = bSecond(object, x);
printf("First: %d, second: %d", f, s);
}
int main()
{
D obj;
pb(&obj, 5);
getchar();
return 0;
}
I have tried to solve this, but I can't. I have a class definition and I want a member function (siz) to return a constant value to another member function (abc). This value is used as maximum index in an array declaration in that function. But this doesn't seems to work. Here is a simplified version:
class bin {
constexpr int siz();
public:
void abc();
};
constexpr int bin::siz() {
const int sizz = sizeof(int) * 8;
}
void bin::abc() {
char arr[siz()]; // compiler: this expression didn't evaluate as constant (¿?)
};
However, this other very similar code (but using simple functions) does compile...
constexpr int siz() {
const int sizz = sizeof(int) * 8;
return sizz;
}
int main() {
char arr[siz()];
return 0;
}
I am not entirely sure but I think the problem is that in bin::abc, the object can be anything at run time. Hence, bin::siz() cannot be evaluated at compile time.
The following works fine
int main()
{
bin b;
char arr[b.siz()];
}
after changing bin to:
class bin {
public:
constexpr int siz();
};
constexpr int bin::siz() {
return sizeof(int) * 8;
}
If siz does not depend on the state of the object, as in your posted code, I suggest making it a static member function.
The following works fine for me.
class bin {
public:
static constexpr int siz();
void abc() const;
};
constexpr int bin::siz() {
return sizeof(int) * 8;
}
void bin::abc() const {
char arr[siz()];
}
int main()
{
bin b;
char arr[b.siz()];
}
I have a class that needs to use some big arrays, initialized via some complex functions, that will be the same for every instance and will only be read after initialization.
I searched on SO and found some answers on initializing static arrays like this:
char A::a[6] = {1,2,3,4,5,6};
But in my case I need to calculate the arrays at runtime via some function.
(How) can I do it?
Re
” will be the same for every instance and will only be read after initialization
Producing a value is the job of a function.
Just define a function that returns the data you need.
You can use it to initialize a static data member (or whatever). For a header only module, if that's relevant, you will need to employ solution to the "inline data" problem, e.g. a Meyers' singleton (a function that returns a reference to a local static variable). Like this:
#include <vector>
namespace my {
using std::vector;
inline
auto squares()
-> vector<int>
{
vector<int> result;
for( int i = 1; i <= 12; ++i ) { result.push_back( i*i ); }
return result;
}
class A
{
private:
static
auto a()
-> const vector<int>&
{
static const vector<int> the_values = squares();
return the_values;
}
public:
A(){}
};
} // namespace my
You can't use {} sintaxis in execution time, you can use a method:
class A
{
static vector<char> a;
//...
public:
static void initStatic();
}
void A::initStatic()
{
a.resize( /*put the size here... */);
for (auto& x : a)
x = //something...
}
vector reference: http://en.cppreference.com/w/cpp/container/vector
If you aren't using vectors, this works. The reason I let A::initialize do the work, rather than just calling one of these externally defined functions, is that we can and should expect the data member a to be private.
//Declare a function pointer type, so you can pass it into A's
//an initialization function takes in the array and its size
typedef void (*initFunction) (char A[], int arraySize);
//see http://www.cprogramming.com/tutorial/function-pointers.html
// for more on function pointers
class A
{
public:
void initialize (initFunction myInitFunction);
...
private:
char a[ARRAYSIZE];
};
void A::initialize (initFunction myInitFunction)
{
(*myInitFunction) (a, ARRAYSIZE);
}
...
A myA;
myA.initialize (yourArrayInitializingFunction);
Or maybe your initialization functions don't take in arrays and initialize them, but return arrays:
class A
{
public:
void initialize (const char* aInit);
...
};
void A::initialize (const char* aInit)
{
for (int i = 0; i < ARRAYSIZE: ++i)
a[i] = aInit[i];
}
...
A myA;
myA.initialize (yourArrayReturningFunction ());
If you're using vectors, code is simpler:
class A
{
public:
void initialize (const vector<char>& aInit) { a = aInit; }
...
private:
vector<char> a;
};
My suggestion:
Instead of using a static member variable, use a static member function to provide access to the array.
In the static member function, create a static function variable that can be populated the first time it is needed.
Here's what I am thinking of:
char* A::getArray()
{
static char a[6] = {0};
static bool inited = false;
if ( !inited )
{
// Initialize the array elements
a[0] = ... ;
...
a[5] = ... ;
inited = true;
}
return a;
}
I've got a class with 3 private variables and one public method, that has 2 char parameter variables.
class InitLine
{
private:
char *a;
char b, c;
public:
InitLine(char *inita, char initc);
Init(char *a, char c);
};
Now the definition of the method is simple:
Initline::Init(char *a, char c)
{
for (b=0; b<c; b++)
*(a+c)=0;
}
Now my question is: If I wish to repeat the same actions with different parametertypes (*a and c, or one of them becomes an integer e.g.), is it necessary to create a new class, or can I use the existing one, doing some 'typecasting' or some other trick I don't know yet?
Thanks and regards
Uwe
Use templates, make the Init function a template of your arguments type.
template <typename T>
Init(char*a , T c){}
for instance
You have many places in your code, which should be fixed prior to any further operations.
Naming convention is terrible. What is a, b, c?
You use b as a loop indexer, while a local variable should be used there instead.
You don't show us, what is a. Where is it allocated? What is the size of memory pointed to by a?
I guess, that your code should look like the following:
class InitLine
{
private:
char * data;
int count;
public:
InitLine(char * newData, int newCount)
{
// Possible error checking?
data = newData;
count = newCount;
}
// No parameters needed here, I guess
void Init()
{
for (int i = 0; i < count; i++)
data[i] = 0;
}
};
As for your question, I'm not really sure, what you are trying to achieve and what do you want to know. If you want to write a generic class holding any type of arrays, you have to use templates:
template <typename T>
class InitLine
{
private:
T * data;
int count;
public:
InitLine(T * newData, int newCount)
{
// Possible error checking?
data = newData;
count = newCount;
}
// No parameters needed here, I guess
void Init()
{
for (int i = 0; i < count; i++)
data[i] = 0;
}
};
You have to use this class in the following way:
InitLine<char> line(myData, myDataSize);
// where myData is a char * and myDataSize is an int
If you want to write a few methods differing by their parameters, this technique is called method overloading and is available in C++:
void Init(char * a, int b) { /* sth */ }
void Init(int * a, int b) { /* sth */ }
Note, that compiler must be able to clearly distinguish, which method should be called. Eg.
void Test(int a) { }
void Test(char a) { }
Test(0); // Ambiguity: which method should be called?
These are only things coming to my mind, while reading your question. If it is not what you are asking for, consider editing the question to be more specific.
If you just want to have the whole class with different types (not just the Init), e.g. also have int *a; int b,c; then template classes are the other trick you don't know yet.
template <typename ANYTYPE> class InitLine
{
private:
ANYTYPE *a;
ANYTYPE b, c;
public:
void InitLine(ANYTYPE *inita, ANYTYPE initc);
void Init(ANYTYPE *a, ANYTYPE c);
};
template <typename ANYTYPE> void Initline<ANYTYPE>::Init(ANYTYPE *a, ANYTYPE c)
{
for (int b=0; b<c; b++)
*(a+c)=0;
}
... main()
{
Initline<int> iline; // initline class based on type int (ANYTYPE -> int)
int line[20];
Initline<char> cline; // initline class based on type char (ANYTYPE -> char)
char somechars[30];
iline.Init(line, 20);
cline.Init(somechars, 30);
The structure is defined as
struct state{
string node_name;
int node_no;
int node_val;
int occupant;
vector<int>node_con;
};
state s[100][100]
I want to send it to a function along with i and j values , where s[i][j] , (i->rows , j-> columns) . How will the struct be sent with both i and j ?
This way
void f(StructName (*a)[100], int i, int j) {
}
Please read about two dimensional arrays and pointer to arrays. Alternatively in C++ you can pass it by a reference, which will make it not decay to its first element
void f(StructName (&a)[100][100], int i, int j) {
}
in C there is no way (AFAIK)
in C++ you could do this
template <class T, int N, int M>
void f(T (&a)[N][M])
{
//...
}
Alternatively, you could pass the dimensions manually, or hard-code them
In C, you can wrap it up in another structure :-)
I see stuff that doesn't look like C in your code ...
struct state {
string node_name;
int node_no;
int node_val;
int occupant;
vector<int>node_con;
};
struct wrap {
int i;
int j;
struct state (*ps)[];
};
int main(void) {
struct state s[100][100];
struct wrap x;
x.i = 100;
x.j = 100;
x.ps = s;
fx(x);
return 0;
}
You mean passing an array of structures. I think it should be this:
struct state{
string node_name;
int node_no;
int node_val;
int occupant;
vector<int>node_con;
};
state s[100][100];
void doSomething(state theState[][100], int i, int j)
{
cout << theState[i][j].node_name << endl;
}
int main()
{
s[0][1].node_name = "s[0][1]";
doSomething(s, 0, 1);
}