Initializing array of structures with function pointer member in C++ - c++

I am having trouble in initializing an array of structures with a function pointer as a member in it.
class Record
{
private:
typedef void (*display_fn_t) ();
struct record {
int a;
display_fn_t disp;
};
static const record rec[];
void disp1() { cout << "Display 1 with a string to display" << endl; }
void disp2() { cout << "Display 2 with an integer to display" << endl; }
public:
int find() { /* logic to find the record comes here */ }
void display() {
for (int i = 0; i < 2; i++) {
rec[i].disp();
}
}
}
const Record::record Record::rec[] = {
{ 10, disp1 },
{ 11, disp2 }
};
int main()
{
Record r;
if (r.find())
r.display();
return 0;
}
When I compile the above code, I am getting the following compilation error:
mca_record.cpp:56: error: argument of type ‘void (Record::)()’ does
not match ‘void (*)()’

Your syntax is wrong and isn't using the appropriate operators.
Fixing a multitude of syntax errors, and stripping out the unrelated find operation, then utilizing proper member function pointers and operator ->* gives the following (one of several ways to do this):
#include <iostream>
class Record
{
private:
typedef void (Record::*display_memfn_t)();
struct record
{
int a;
display_memfn_t disp;
};
static const record rec[];
void disp1() { std::cout << "Display 1 with a string to display" << std::endl; }
void disp2() { std::cout << "Display 2 with an integer to display" << std::endl; }
public:
void display();
};
const Record::record Record::rec[] =
{
{ 10, &Record::disp1 },
{ 11, &Record::disp2 }
};
void Record::display()
{
for (size_t i=0; i<sizeof rec/sizeof*rec; ++i)
(this->*(rec[i].disp))();
}
int main()
{
Record r;
r.display();
return 0;
}
Output
Display 1 with a string to display
Display 2 with an integer to display
Compare it to your existing code, and not in particular that pointers to member functions are not simply pointers to functions. They require different handling and generally different operators to utilize. See here for different methods of member access (both variable and function).
Best of luck.

To make the call work you must invoke it like this:
for (int i = 0; i < 2; i++) {
(*rec[i].disp)();
}
And initialize the table this way:
const Record::record Record::rec[] = {
{ 10, &Record::disp1 },
{ 11, &Record::disp2 }
};

Related

How do you call a function from a pointer array to a class method in C++? [duplicate]

This question already has answers here:
C++ Call Pointer To Member Function
(4 answers)
Closed 1 year ago.
I'm pretty new to C++
I have this code:
in my class.hpp
class Dummy {
private:
void f1(void);
void f2(void);
void f3(void);
void f4(void);
public:
void caller(std::string id);
};
in my class.cpp
void Dummy::caller( std::string id ) {
// something something about qualifiers requires Dummy::*f instead of just *f
void (Dummy::*f[4])() = {&Dummy::f1, &Dummy::f2, &Dummy::f3, &Dummy::f4};
string v[4] = {"f1", "f2", "f3", "f4"};
for (int i = 0; i < 4; i++) {
if (id == v[i]) {
(*f[i])();
break ;
}
}
}
this (*f[i])() is valid in C code, but for some reason in C++, it shows me this error which i googled but was unlucky and found nothing that useful, except for std::invoke which is in C++17 (?), and I'm bound to C++98
The error:
Class.cpp:41:5: error: indirection requires pointer operand ('void (Dummy::*)()' invalid)
(*f[i])();
^~~~~
well, this is not how c++ works...
just because you define functions like
void f1(void);
void f2(void);
void f3(void);
void f4(void);
doesnt mean you can access them or handle then like you were working with an array
but that is the key to solve that,
you can create an array of functions and call it by index
here is a short example of how you can achieve that:
#include <iostream>
void f1(void)
{
std::cout << "you are in f1" << std::endl;
}
void f2(void)
{
std::cout << "you are in f2" << std::endl;
}
void f3(void)
{
std::cout << "you are in f3" << std::endl;
}
void f4(void)
{
std::cout << "you are in f4" << std::endl;
}
void (*p[4]) (void);
int main(void)
{
int result;
int i, j, op;
p[0] = f1;
p[1] = f2;
p[2] = f3;
p[3] = f4;
for(auto i= 0; i<4; ++i)
{
(*p[i])();
}
return 0;
}

Passing member function to member object into template parameter

I am trying to create a class/struct that can take in a struct/class of different types that all have the function update().
I want to get the update() function and then put it in a vector as a pointer and then call it later, but I'm having trouble putting member function pointers into a vector, but I am having no problem putting 'classless' function pointers into the vector.
How can I put the member function pointers into the vector?
Here is my code
#include <vector>
#include <iostream>
#include <stdio.h>
using namespace std;
struct typeA
{
public:
int data = 0;
void update()
{
cout << "hello, my data is " << data << endl;
}
};
struct typeB
{
float data = 0;
void update()
{
cout << "hi, my data is " << data << endl;
}
};
class typeListTwo
{
typedef void(*updaterFunc)();
vector <updaterFunc> items;
public:
typeListTwo()
{
}
~typeListTwo()
{
items.~vector();
}
void addItem(updaterFunc newItem)
{
items.push_back(newItem); //This works
}
void doWork()
{
for (unsigned int funcIndex = 0; funcIndex < items.size(); funcIndex++)
{
items[funcIndex]();
}
}
};
class typeList
{
typedef void(*updaterFunc)();
vector <updaterFunc> items;
public:
typeList()
{
}
~typeList()
{
items.~vector();
}
template <class Item>
void addItem(Item newItem)
{
items.push_back(newItem.update); //But this does not?
//newItem.update(); //This also works by itself
}
void doWork()
{
for (unsigned int funcIndex = 0; funcIndex < items.size(); funcIndex++)
{
items[funcIndex]();
}
}
};
void aFunc()
{
cout << "123 hello" << endl;
}
void bFunc()
{
cout << "456 goodbye" << endl;
}
int main()
{
typeA aThing;
typeB bThing;
typeList listThings;
typeListTwo listThingsTwo;
aThing.data = 128;
bThing.data = -3.234;
listThings.addItem(aThing);
listThings.addItem(bThing);
listThings.doWork();
listThingsTwo.addItem(aFunc);
listThingsTwo.addItem(bFunc);
listThingsTwo.doWork();
return 0;
}
The way to go is to use std::function or use interface:
class typeList
{
std::vector<std::function<void()>> items;
public:
template <class Item>
void addItem(Item& item)
{
// Care: life time of item should be bigger than this instance
items.push_back([&](){ item.update(); });
}
void doWork()
{
for (auto& f : items)
{
f();
}
}
};

Why is the error "not declared in this scope" shows?

I am a beginner in C++. I am learning the topic friend functions. I have the code below in which two friend functions are declared in the class and called by the constructor but an error shows that the declared friend member functions are not declared in the scope. What am I doing wrong here? here is my code:
#include <iostream.h>
class Salary
{
private:
int sal[10];
public:
friend void add_details();
void display();
friend void display_des();
Salary()
{
add_details();
}
};
void add_details()
{
int loop = 0;
for(loop=0;loop<10;loop++)
{
cin >> sal[loop];
if (sal[loop] <= 0)
{
cout << "The amount should be greater than 0" << endl;
loop = loop - 1;
continue;
}
}
}
void display_des()
{
int sal_des[10];
int loop1 = 0, loop2;
for(loop1=0; loop1<10; loop1++)
{
sal_des[loop1] = sal[loop1];
}
for (loop1=0; loop1<10; loop1++)
{
for(loop2=loop1+1; loop2<10; loop2++)
{
if (sal_des[loop1]< sal_des[loop2])
{
int temp;
temp = sal_des[loop1];
sal_des[loop1] = sal_des[loop2];
sal_des[loop2] = temp;
}
}
}
for(loop1=0; loop1<10; loop1++)
{
cout << sal_des[loop1];
}
}
int main()
{
Salary sal1;
sal1.display_des();
return 0;
}
Also, another error inside function display_des() is shown as sal is not declared in this scope
You are defining a global function
void display_des();
instead of the member function
void Salary::display_des();
That means display_des has no "this"- Salary-object from which it could take the member sal[]. You also don't pass it a Salary-object from outside, so which sal[] should it use?
So either you use a friend function like this:
void display_des(Salary& obj){
obj.sal[...]...
}
Or you use a member-function, similar to this:
class Salary
{
private:
int sal[10];
public:
(...)
void display_des();
(...)
};
(...)
void Salary::display_des(){
sal[...]...
(...)
}

Array class in C++: How to use one method in another

I have a class for performing various array operations. I like to use my insert method in my populate method.
Can someone guide me on that? Here is the code:
#include <iostream>
#include <cstdlib>
using namespace std;
const int MAX=5;
class array
{
private:
int arr[MAX];
public:
void insert(int pos, int num);
void populate(int[]);
void del(int pos);
void reverse();
void display();
void search(int num);
};
void array::populate(int a[])
{
for (int i=0;i<MAX;i++)
{
arr[i]=a[i];
}
}
void array::insert(int pos, int num)
{
for (int i=MAX-1;i>=pos;i--)
{
arr[i] = arr[i-1];
arr[i]=num;
}
}
void array::del(int pos)
{
for (int i=pos;i<MAX;i++)
{
arr[pos]=arr[pos + 1];
}
}
void array::display()
{
for (int i=0;i<MAX;i++)
cout<<arr[i];
}
void array::search(int num)
{
for (int i=0;i<MAX;i++)
{
if (arr[i]==num)
{
cout<<"\n"<<num<<" found at index "<<i;
break;
}
if (i==MAX)
{
cout<<num <<" does not exist!";
}
}
}
int main()
{
array a;
for (int j=0;j<MAX;j++)
{
a.insert(j,j);
}
a.populate(a);
a.insert(2,7);
a.display();
a.search(44);
system("pause");
}
I like to use my insert method in my
populate method. Can someone guide me
on that?
That would mean that instead of the straightforward and efficient "copy from one array to another" approach, you'd call insert for each value of the input with the correct index in place of the assignment.
To call a method on the current instance, from inside a method:
insert(x, y);
//or
this->insert(x, y);
Your code also contains an error, in that you pass a wrong type to populate in main. It expect int* (a real array), not an array object.
Please elaborate your question. If you just need a good container have a look at the STL (Standard Template Library) std::vector. It's part of the C++ standard and comes with your compiler.
If you want to learn how to write a custom class, please try to be more precise in your question.
Also consider the wealth of beginner tutorials available on the net, for example:
http://www.learncpp.com/
Here is a little example on how to write a custom class with one member function calling the other and accessing a private data member (note that inside a member function you can refer to any other member directly):
#include <iostream>
class Example
{
private:
int some_private_stuff;
public:
Example();
void function_a();
void function_b();
};
Example::Example(){
some_private_stuff = 1;
}
void Example::function_a(){
std::cout << "this is function a" << std::endl;
some_private_stuff = 2;
std::cout << "changed private_stuff to " << some_private_stuff << std::endl;
}
void Example::function_b(){
std::cout << "this is function b" << std::endl;
function_a();
}
int main() {
Example e;
e.function_b();
return 0;
}

C++ function pointer (class member) to non-static member function

class Foo {
public:
Foo() { do_something = &Foo::func_x; }
int (Foo::*do_something)(int); // function pointer to class member function
void setFunc(bool e) { do_something = e ? &Foo::func_x : &Foo::func_y; }
private:
int func_x(int m) { return m *= 5; }
int func_y(int n) { return n *= 6; }
};
int
main()
{
Foo f;
f.setFunc(false);
return (f.*do_something)(5); // <- Not ok. Compile error.
}
How can I get this to work?
class A{
public:
typedef int (A::*method)();
method p;
A(){
p = &A::foo;
(this->*p)(); // <- trick 1, inner call
}
int foo(){
printf("foo\n");
return 0;
}
};
void main()
{
A a;
(a.*a.p)(); // <- trick 2, outer call
}
The line you want is
return (f.*f.do_something)(5);
(That compiles -- I've tried it)
"*f.do_something" refers to the pointer itself --- "f" tells us where to get the do_something value from. But we still need to give an object that will be the this pointer when we call the function. That's why we need the "f." prefix.
class A {
int var;
int var2;
public:
void setVar(int v);
int getVar();
void setVar2(int v);
int getVar2();
typedef int (A::*_fVar)();
_fVar fvar;
void setFvar(_fVar afvar) { fvar = afvar; }
void insideCall() { (this->*fvar)(); }
};
void A::setVar(int v)
{
var = v;
}
int A::getVar()
{
std::cout << "A::getVar() is called. var = " << var << std::endl;
return var;
}
void A::setVar2(int v2)
{
var2 = v2;
}
int A::getVar2()
{
std::cout << "A::getVar2() is called. var2 = " << var2 << std::endl;
return var2;
}
int main()
{
A a;
a.setVar(3);
a.setVar2(5);
// a.fvar = &A::getVar;
a.setFvar(&A::getVar);
(a.*a.fvar)();
a.setFvar(&A::getVar2);
(a.*a.fvar)();
a.setFvar(&A::getVar);
a.insideCall();
a.setFvar(&A::getVar2);
a.insideCall();
return 0;
}
I extended Nick Dandoulakis's answer. Thank you.
I added a function which set the member function pointer from outside of the class. I added another function which can be called from outside to show inner call of member function pointer.
Try (f.*do_something)(5);
#include<iostream>
using namespace std;
class A {
public:
void hello()
{
cout << "hello" << endl;
};
int x = 0;
};
void main(void)
{
//pointer
A * a = new A;
void(A::*pfun)() = &A::hello;
int A::*v1 = &A::x;
(a->*pfun)();
a->*v1 = 100;
cout << a->*v1 << endl << endl;
//-----------------------------
A b;
void(A::*fun)() = &A::hello;
int A::*v2 = &A::x;
(b.*fun)();
b.*v2 = 200;
cout << b.*v2 << endl;
}
I think calling a non static member of the class could also be done using a static member function.