class::data_member vs class_object.data_member - c++

I just saw a post in which I found something I never saw before, in short here it is:
class A {
public:
int _x;
};
void foo(A *a_ptr, int *m_ptr)
{
cout << (*a_ptr).*m_ptr << endl; // here
}
int main()
{
A a;
a._x = 10;
foo(&a, &A::_x); // and here
}
How could it be done? Pass in &A::_x, and later refer it using (*a_ptr).*m_ptr?
I thought, &A::_x will always refer to the same address, but different objects have different _x, how could it be done?

&A::_x is a pointer-to-member, which is not a pointer. Rather, think of it as some relative sort of construct which tells you where inside an object you find a particular member element. Only together with an instance reference can you locate the actual subobject of that instance which is given by the member pointer.
Compare:
struct Foo { int x; int y; };
Foo a = { 1, 2 };
Foo b = { 3, 4 };
Foo c = { 5, 6 };
int * p = &a.x; // ordinary pointer-to-int
int Foo::*pm = &Foo::x; // pointer-to-member
int result = a.*pm + b.*pm + c.*pm; // aggregate Foo::x
// point to a different member:
pm = &Foo::y;
result = a.*pm + b.*pm + c.*pm; // aggregate Foo::y

Related

How to initialise struct with constant members with certain address?

I am trying to initialise class object (which has constant members) with certain values and certain address. I understand that this is because members are constant but I need them to be constant. I tried to find solution but with no success.
So the question is: is there some "easy" way to do it?
class ints{
public:
const int a;
const int b;
ints(int a, int b);
};
ints::ints(int a, int b) :
a{a},
b{b}
{}
int main() {
auto ptr = (ints*)malloc(sizeof(ints));
ints values{1, 2};
// all wrong
// *ptr = ints copy{values};
// &values = ptr;
// *ptr = values;
std::cout << ptr->a; //ptr->a should be equal to 1
}
You can create an object at a specific address using placement-new:
extern void* some_address;
int main()
{
ints* ptr = new(some_address) ints{1, 2};
std::cout << ptr->a;
}

callback in C++ struct

I have been trying to implement a callback function in c++. Within a class, I have a struct, a number of methods, and a method that creates an instance of the struct with one of the other methods as its argument.
The struct has many other variables, but an illustration is depicted here:
class MYCLASS
{
public:
MYCLASS();
struct TEST{
std::function<int(int)> foo;
};
int plus(int x){
return x + 1;
}
int minus(int x){
return x - 1;
}
void sim(){
TEST T; // make an instance of TEST
T.foo = plus(5); // assign TEST.foo a function (plus or minus)
T.foo(); // call the method we assigned
}
};
Within the sim method, I want to create an instance of test and give it either plus or minus, depending on some criterion. Both lines where I try and give the instance T a plus function and subsequently call it are incorrect.
If you want to delay the call to T.foo, then you could use a lambda like this:
T.foo = [this](int x) { return plus(x); };
T.foo(5);
Option - 1
If the member functions plus() and minus() are simple enough like you have shown, you can make them as lambda functions inside the struct TEST.
Since the capture-less lambdas can be stored in typed function pointers, the following will do what you want.
See live demo
#include <iostream>
class MYCLASS
{
int m_var = 5; // just for demonstration
public:
MYCLASS() = default;
struct TEST
{
using fPtrType = int(*)(int); // function pointer type
const fPtrType foo1 = [](int x) { return x + 1; }; // plus function
const fPtrType foo2 = [](int x) { return x - 1; }; // minus function
};
void sim()
{
TEST T;
std::cout << "Answer from int PLUS(int): " << T.foo1(m_var) << std::endl;
std::cout << "Answer from int MINUS(int): " << T.foo2(m_var) << std::endl;
}
};
Option - 2
If the above alter a lot in your code, use typed function pointer again for member functions and do as follows; which will avoid unnecessary copying(by capturing) the class instance to the lambda and template instantiation and other performance issues comes along with std::function as well.
See live demo
#include <iostream>
class MYCLASS
{
using fPtrType = int(MYCLASS::*)(int); // class member function pointer type
public:
MYCLASS() = default;
struct TEST { fPtrType foo = nullptr; };
int plus(int x) { return x + 1; }
int minus(int x) { return x - 1; }
void sim()
{
TEST T;
T.foo = &MYCLASS::plus; // now you can
std::cout << "Answer from int PLUS(int): " << (this->*T.MYCLASS::TEST::foo)(5) << std::endl;
//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ syntax would be a bit ugly
// later same ptr variable for minus()
T.foo = &MYCLASS::minus;
int answer = (this->*T.MYCLASS::TEST::foo)(5);
std::cout << "Answer from int MINUS(int): " << answer << std::endl;
}
};
int main()
{
MYCLASS obj;
obj.sim();
return 0;
}
Output:
Answer from int PLUS(int): 6
Answer from int MINUS(int): 4

Can a member variable access the value of a previously defined member variable in the same initialization list (C++)?

For example:
Cls::Cls(int *p) : m1_(1), m2_(m1), m3_(p), m4_(m3) {}
where Cls::m1_ and Cls::m2_ are of type int and m3 and m4 are of type int*.
Is this legal? If it is legal, does it do what one would expect?
Yes, it's legal. The init order follows the order of the members in the class.
struct C
{
C() : m1_(1), m2_(m1_ + 1), m3_(m2_ + 2), m4_(m3_ + 3) {}
int m1_ = 0;
int m2_ = 0;
int m3_ = 0;
int m4_ = 0;
};
int main()
{
C c;
std::cout << c.m1_ << std::endl;
std::cout << c.m2_ << std::endl;
std::cout << c.m3_ << std::endl;
std::cout << c.m4_ << std::endl;
}
The output:
1
2
4
7
But if you modified the member orders:
struct C
{
C() : m1_(1), m2_(m1_ + 1), m3_(m2_ + 2), m4_(m3_ + 3) {}
int m2_ = 0;
int m3_ = 0;
int m4_ = 0;
int m1_ = 0;
};
The output will be:
1
1
3
6
As pointed out in the comments, non-static data members are initialized in declaration order. In order to prevent confusion, you should always write the member initializers in declaration order. In the case presented in the question, I will therefore assume that the order in which the members were declared is:
int m1_;
int m2_;
int* m3_;
int* m4_;
Assuming that is the case, the code is well-defined and does what you expect it to do. This is guaranteed by [intro.execution]/12.3, which guarantees that each member initialization is a full-expression, and [class.base.init]/13.3, which guarantees that these initializations occur in declaration order.
This is legal-ish. If you have
struct foo
{
int a;
int b;
int c;
foo() : a(1), b(a + 1), c(b + 1) {}
};
Then this is fine. The reason is a is declared in the class before b and b is declared before c. All class members are initialized in the order they are declared in the class, so you could even have
struct foo
{
int a;
int b;
int c;
foo() : c(b + 1), b(a + 1), a(1) {}
};
and you would still be okay. If you had
struct foo
{
int b;
int c;
int a;
foo() : a(1), b(a + 1), c(b + 1) {}
};
on the other hand, both b and c would be initialized with an indeterminate value and using them would be undefined behavior.

C++ Pointer to struct member

If I were to make a struct, say:
struct FOO{
int x, y, z, a, b, c;
}
int main(){
FOO foo = {1, 2, 3, 4, 5, 6};
return 0;
}
Would there be anyway to create a pointer that can access FOO's integer members?
Maybe by making pointer that points to foo and then somehow modifying it to increment in integers?
I know that if I were to make FOO a class instead with a method that returns a pointer to the first int, then I could cycle though the members with ++ or [i](in a for loop). But I want to know if I can access structure members simply by knowing the address of the struct (assuming I have a good understanding of how to navigate said struct)
Any insight would be much appreciated.
Thanks!
You can overload operator[] for the struct:
struct bar // ALL_UPPERCASE is for macros!
{
int a, b, c, d, e, f;
int operator[](size_t i) const
{
switch(i)
{
case 0: return a;
case 1: return b;
case 2: return c;
case 3: return d;
case 4: return e;
case 5: return f;
default: assert(false);
}
}
};
Just a thought and this might not work, but you could try doing a pointer to the foo struct and then shifting the pointer by the size of an int for each element. So something like:
int * ptr= & foo;
ptr++;
If I'm remembering my hardware design class well enough a struct is actually really similar to an array in memory it can just have variable sized blocks of memory for each of its indices.
struct FOO{
int x, y, z, a, b, c;
} __attribute__ ((packed))
FOO foo;
int *i = &foo;
In this case, the attribute ((packed)) eliminates the problem created by padding, since it get's rid of it. Afterwards incrementing i, grantees that it will be in the next element of the struct.
It's pretty straightforward:
Foo foo = { 1, 2, 3, 4, 5, 6 };
int* pfoo = &foo.x;
int structMembers = sizeof(Foo) / sizeof(int);
for (int i = 0; i < structMembers; i++)
{
cout << pfoo[i] << endl;
}
There's no difference between a struct and class aside from default access modifier (private in structs, public in classes). Thus whatever you can do with classes, you can do with structs.
As I understood you need this: https://en.cppreference.com/w/cpp/utility/functional/mem_fn
if you need own implementation take this:
#include <iostream>
struct Foo
{
int a = 1;
char b = 'a';
};
template<typename Struct, typename var_type>
const var_type member_get( Struct& obj, var_type Struct::* mem_var ) { return
obj.*mem_var; }
int main()
{
Foo x;
std::cout << member_get( x, &Foo::a ) << std::endl;
std::cout << member_get( x, &Foo::b ) << std::endl;
return 0;
}

Define struct array in function

The code:
int i;
struct st
{
int m;
}st_t[2];
void foo()
{
i = 4;
st_t[2] =
{
{10},{20}
}; // it's wrong !!!! but I don't know how to do.
}
int main()
{
foo();
cout<<i<<endl; // will output 4;
cout<<st_t[0].m<<endl; // this should output 10
cout<<st_t[1].m<<endl; // this should output 20
return 0;
}
Is it possible to define a struct array in a function? If it is, then how to do this?
Thanks in advance.
PS:
Sorry my English is not good. I am making a Tetris game, it have a Shape class, I declared a shape struct array in Shape.h, then I assign to the struct array in Shape constructor function in Shape.cpp. Is it right? or how to assign to the struct array so I can use it in another function?
You can initialize an array in the place where it's defined. I.e. either move the definition into the function, or move the initialization out of the function:
struct st
{
int m;
}
st_t[2] = {{10},{20}};
Instead of the direct assignment of values, you can initialize a temporary variable and copy this variable to your global variable:
Delete:
...
st_t[2] = {
{10},{20}
};
...
and add:
...
st tmp[2] = { {10}, {20} };
memcpy(st_t, tmp, sizeof st_t);
...
Addendum:
If it doesn't work for you, there might be another error in your code. From your example:
#include <iostream>
#include <memory.h>
using namespace std;
int i;
struct st { int m; } st_t[2];
void foo()
{
i = 4;
st tmp[2] = { {10}, {20} };
memcpy(st_t, tmp, sizeof st_t); // use: const_addr instead of &const_addr
}
int main()
{
foo();
cout << i << endl; // will output 4;
cout << st_t[0].m << endl; // this should output 10
cout << st_t[1].m << endl; // this should output 20
return 0;
}
all works fine as expected.
If you want to define an array in the function (as your question title and text implies), then add the type specifier st to the definition:
st st_t[2] =
{
{10},{20}
};
However, this will be a separate array to the global one, and so the output from main() won't match what your comments say should happen. If you actually want to assign to the global array, then:
st_t[0].m = 10;
st_t[1].m = 20;
or, in C++11, you can use similar syntax to your example if you replace the plain array with std::array:
std::array<st, 2> st_t;
void foo() {
// Note the extra braces - std::array is an aggregate containing an array
st_t =
{{
{10},{20}
}};
}
If you only want the variable at function scope then
void foo() {
struct {
int m;
} st_t = { {10}, {20} };
// do something
}