i have 2 classes say "Class A" and "Class B". i tried to declare the function pointer prototype in "Class A" and use it in "Class B", but failed. Please look in to my sample code and assist me how to make it success.
#include "stdafx.h"
#include <iostream>
using namespace std;
class A
{
public:
int (*funcPtr)(int,int);
void PointerTesting(int (*funcPtr)(int,int))
{
//i need to get B::test as an function pointer argument
}
};
class B
{
public:
int test(int a,int b)
{
return a+b;
}
};
int _tmain(int argc, _TCHAR* argv[])
{
int (A::*fptr) (char*) = &B::test;
getchar();
return 0;
}
Recommendation: Use < functional >, std::function and std::bind
#include <iostream>
#include <functional>
using namespace std;
class A {
public:
using FnPtr = std::function<int(int, int)>;
void PointerTesting(const FnPtr& fn) {
//i need to get B::test as an function pointer argument
// Example: Print 1 and 2's sum.
int result = fn(1, 2);
std::cout << "Result: " << result << std::endl;
}
};
class B {
public:
int test(int a,int b) {
return (a+b);
}
};
int main(int argc, char* argv[]) {
A a;
B b;
A::FnPtr ptr = std::bind(&B::test, b, std::placeholders::_1, std::placeholders::_2);
a.PointerTesting(ptr);
getchar();
return 0;
}
http://en.cppreference.com/w/cpp/utility/functional/bind
http://en.cppreference.com/w/cpp/utility/functional/function
Related
This prints nothing:
#include <iostream>
template <typename Derived>
struct A
{
static int test()
{
std::cout << "test" << std::endl;
return 0;
}
static inline int a = test();
};
struct B : public A<B>
{
};
int main(int argc, char** argv)
{
return EXIT_SUCCESS;
}
But this does:
#include <iostream>
template <typename Derived>
struct A
{
};
struct B : public A<B>
{
static int test()
{
std::cout << "test" << std::endl;
return 0;
}
static inline int a = test();
};
int main(int argc, char** argv)
{
return EXIT_SUCCESS;
}
And also this:
#include <iostream>
struct A
{
static int test()
{
std::cout << "test" << std::endl;
return 0;
}
static inline int a = test();
};
struct B : public A
{
};
int main(int argc, char** argv)
{
return EXIT_SUCCESS;
}
Not sure why or a workaround. I need the 'Derived' type to register it into a static table.
The reason why the first snippet doesn't print anything is that the static variable is not instantiated. You have to use that variable in order to instantiate it.
[temp.inst]/2
The implicit instantiation of a class template specialization causes
the implicit instantiation of the declarations, but not of the
definitions, default arguments, or noexcept-specifiers of the class
member functions, member classes, scoped member enumerations, static
data members, member templates, and friends
As a workaround, you can just use that variable:
int main(int argc, char** argv)
{
(void) B::a;
return EXIT_SUCCESS;
}
Since A is a template class, the static inline function/variable are not actually instantiated from the template unless they are used. Thus, you could do e.g. this:
#include <iostream>
template <typename Derived>
struct A
{
static int test()
{
std::cout << "test" << std::endl;
return 0;
}
static inline int a = test();
};
struct B : public A<B>
{
static inline int b = a;
};
int main(int argc, char** argv)
{
return 0;
}
Demo
The (automatic) solution, as pointed here is to create a constructor that uses the registration variable. Also, the variable will be initialized only if an object is constructed.
#include <iostream>
template <typename Derived>
struct A
{
A()
{
a = 0;
}
static int test()
{
std::cout << "test" << std::endl;
return 0;
}
static inline int a = test();
};
struct B : public A<B>
{
};
int main(int argc, char** argv)
{
B b;
return EXIT_SUCCESS;
}
The 'a = 0' is to avoid a warning of unused variable. Overhead should be minimal.
Demo
I have the following problem.
I have a base abstract class with a pure virtual method, and I want to pass it as an argument to another member function(so not a normal function). Yet I have an error when trying to call the method with specified function. Code speaks better than words so bellow I have posted the code that generates the problem
class BaseClass
{
public:
BaseClass();
int add(int, int);
virtual void op(void (*f)(int, int), string s, int a, int b) = 0;
~BaseClass();
};
#include "BaseClass.h"
class ClasaDerviata:public BaseClass
{
public:
ClasaDerviata();
void testNumere(int a, int b);
void op(void(*f)(int, int), string s, int a, int b);
~ClasaDerviata();
};
#include "BaseClass.h"
BaseClass::BaseClass()
{
}
int BaseClass::add(int a, int b)
{
return a + b;
}
BaseClass::~BaseClass()
{
}
#include "ClasaDerviata.h"
#include <iostream>
using namespace std;
ClasaDerviata::ClasaDerviata()
{
}
void ClasaDerviata::testNumere(int a, int b)
{
cout << a + b << "\n";
cout << " suma " << add(a,b) << "\n";
}
void ClasaDerviata :: op (void (*f)(int, int), string s, int a, int b)
{
f(a, b);
cout << s << "\n";
}
ClasaDerviata::~ClasaDerviata()
{
}
#include "ClasaDerviata.h"
#include <iostream>
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
ClasaDerviata *a;
a = new ClasaDerviata();
int x, y;
cin >> x >> y;
a->op(&ClasaDerviata::testNumere, "test metoda", x, y);
system("pause");
return 0;
}
Thank you for your time!
void ClasaDerviata::testNumere(int a, int b); is not of type void (*)(int, int) but void (ClasaDerviata::*)(int, int)
You may add static to testNumere and add to fix your problem or change signature of your function (and change internal code too).
Remember when you make a call to a member function a hidden parameter 'this' is passed. So your ClasaDerviata::testNumere(int a, int b); function actually takes three parameters.
I would suggest to read Joseph Garvin comment in
How can I pass a class member function as a callback?
he has explained it very well.
How could I keep an object valid in a different class? Here is an example below.
This code would give as a result on the screen:
2
2
What I want is to give me this:
2
3
In other words, I desire object Bita (or even the whole class two) to acknowledge object Alpha and not create a new object.
Is there a way to include the object Alpha to object Bita ? Please be simple because I am a beginner.
#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <stdlib.h>
#include <stdio.h>
using namespace std;
class one
{
int a, b;
public:
one() { a = 2; }
int func()
{
return a;
}
void func2()
{
a = 3;
}
};
class two
{
int z, b;
public:
void test();
};
void two::test()
{
one Alpha;
cout << Alpha.func() << '\n';
}
int main()
{
one Alpha;
cout << Alpha.func() << '\n';
Alpha.func2();
two Bita;
Bita.test();
return 0;
}
Each instance of an object has its own values for its member variables. So when you declare two Bita, and call Bita.test(), test() creates its own object of class Alpha inside of it, with its own value, which is still at 2, prints that, and then that Alpha object goes out of scope and is removed from the stack as test() completes.
What you say you have in mind to do here is to have class one have what is called a static member variable. Add the keyword static:
static int a;
And then a will behave as you intend.
One explanation of this is here: http://www.learncpp.com/cpp-tutorial/811-static-member-variables/
One solution would be to pass the object by reference you method two::test like this
class two
{
int z, b;
public:
void test(one& a);
};
void two::test(one& a)
{
cout << a.func() << '\n';
}
And then call it in main
Bita.test(Alpha);
So the full code will be
#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <stdlib.h>
#include <stdio.h>
using namespace std;
class one {
int a, b;
public:
one() { a = 2; }
int func() { return a; }
void func2() { a = 3; }
};
class two {
int z, b;
public:
void test(one&);
};
void two::test(one& a) {
cout << a.func() << '\n';
}
int main() {
one Alpha;
cout << Alpha.func() << '\n';
Alpha.func2();
two Bita;
Bita.test(Alpha);
return 0;
}
this is what I tried (the functions "fun" must be static):
#include<iostream>
class A
{
public:
static void fun(double x) { std::cout << "double" << std::endl; }
};
class B
{
public:
static void fun(int y) { std::cout << "int" << std::endl; }
};
class C
:
public A,
public B
{
};
int main(int argc, const char *argv[])
{
double x = 1;
int y = 1;
C::fun(x);
C::fun(y);
return 0;
}
and using g++ (GCC) 4.8.1 20130725 (prerelease), I got the following error:
main.cpp: In function 'int main(int, const char**)':
main.cpp:27:5: error: reference to 'fun' is ambiguous
C::fun(x);
^
main.cpp:12:21: note: candidates are: static void B::fun(int)
static void fun(int y) { std::cout << "int" << std::endl; }
^
main.cpp:6:21: note: static void A::fun(double)
static void fun(double x) { std::cout << "double" << std::endl;
So my question is: how come in C++ if I can override member functions, and not static functions? Why isn't overloading is not working in this scenario? I would expect the compiler to bring "fun" into the namespace C:: and then do name mangling and use overloading to distinguish C::fun(int) and C::fun(double).
You need to put them into scope yourself:
class C
:
public A,
public B
{
public:
using A::fun;
using B::fun;
};
What you need is in class C's definition:
public:
using A::fun;
using B::fun;
It is not clear what fun() method you want to call, therefore you must specify which one you want:
int main(int argc, const char *argv[])
{
double x = 1;
int y = 1;
A::fun(x);
B::fun(y);
return 0;
}
I am trying to create a generic function map using templates.The idea is to inherit from this generic templated class with a specific function pointer type. I can register a function in the global workspace, but I'd rather collect all the functions together in the derived class and register these in the constructor. I think I am almost here but I get a compile error. Here is a stripped down version of my code:
#include <iostream>
#include <string>
#include <map>
#include <cassert>
using namespace std;
int f(int x) { return 2 * x; }
int g(int x) { return -3 * x; }
typedef int (*F)(int);
// function factory
template <typename T>
class FunctionMap {
public:
void registerFunction(string name, T fp) {
FunMap[name] = fp;
}
T getFunction(string name) {
assert(FunMap.find(name) != FunMap.end());
return FunMap[name];
}
private:
map<string, T> FunMap;
};
// specific to integer functions
class IntFunctionMap : public FunctionMap<F> {
public:
int f2(int x) { return 2 * x; }
int g2(int x) { return -3 * x; }
IntFunctionMap() {
registerFunction("f", f); // This works
registerFunction("f2", f2); // This does not
}
};
int main()
{
FunctionMap<F> fmap; // using the base template class directly works
fmap.registerFunction("f", f);
F fun = fmap.getFunction("f");
cout << fun(10) << endl;
return 0;
}
The error I get is:
templatefunctions.cpp: In constructor ‘IntFunctionMap::IntFunctionMap()’:
templatefunctions.cpp:33: error: no matching function for call to ‘IntFunctionMap::registerFunction(const char [3], <unresolved overloaded function type>)’
templatefunctions.cpp:15: note: candidates are: void FunctionMap<T>::registerFunction(std::string, T) [with T = int (*)(int)]
Juan's answer is correct: member functions have an implicit first parameter, which is a pointer to the type of which they are a member. The reason your code fails to compile is that your map supports function pointers with type int (*)(int), but the type of f2 is int (IntFunctionMap::*)(int).
In the specific case that you show here, you can use std::function, which implements types erasure, to present free functions and member functions as the same type. Then you could do what you are trying to do. Note: this requires C++11.
#include <iostream>
#include <string>
#include <map>
#include <cassert>
#include <function>
#include <bind>
using namespace std;
int f(int x) { return 2 * x; }
int g(int x) { return -3 * x; }
typedef std::function<int (int)> F;
// function factory
template <typename T>
class FunctionMap {
public:
void registerFunction(string name, T fp) {
FunMap[name] = fp;
}
T getFunction(string name) {
assert(FunMap.find(name) != FunMap.end());
return FunMap[name];
}
private:
map<string, T> FunMap;
};
// specific to integer functions
class IntFunctionMap : public FunctionMap<F> {
public:
int f2(int x) { return 2 * x; }
int g2(int x) { return -3 * x; }
IntFunctionMap() {
registerFunction("f", f); // This works
registerFunction("f2", std::bind(&f2, this, _1)); // This should work, too!
}
};
int main()
{
FunctionMap<F> fmap; // using the base template class directly works
fmap.registerFunction("f", f);
F fun = fmap.getFunction("f");
cout << fun(10) << endl;
return 0;
}