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.
Related
I started to learn some oop and I have a question, why I can't put the function in first class, I know there is a way to write the friend method down under second class. If I put it in the first class where it belongs my compiler shows the error C2027: "Error C2027 use of undefined type 'Calculator'"
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <ctime>
using namespace std;
class Calculator;
class PlacadeBaza {
char denumire_procesor[100];
public:
char* getDenumire() {
return denumire_procesor;
}
void set(Calculator a, PlacadeBaza b, int memorie, char denumire[100]) { //C2027
a.memorie_RAM = memorie;
strcpy(b.denumire_procesor, denumire); //C2027
}
};
class Calculator {
int memorie_RAM;
public:
int getMemorie_RAM() {
return memorie_RAM;
}
friend void PlacadeBaza::set(Calculator a, PlacadeBaza b, int memorie, char denumire[100]);
};
int main() {
Calculator a;
PlacadeBaza b;
int memorie;
char denumire[100];
cin >> memorie >> denumire;
b.set(a, b, memorie, denumire);
cout << a.getMemorie_RAM();
cout << b.getDenumire();
}
Setting aside other issues with the code, if you wish PlacadeBaza to be able to access private members of Calculator you need to declare that PlacadeBaza is a friend class of Calculator.
#include <iostream>
#include <ctime>
using namespace std;
class PlacadeBaza;
class Calculator {
int memorie_RAM;
public:
int getMemorie_RAM() {
return memorie_RAM;
}
friend class PlacadeBaza;
};
class PlacadeBaza {
char denumire_procesor[100];
public:
char* getDenumire() {
return denumire_procesor;
}
void set(Calculator a, PlacadeBaza b, int memorie, char denumire[100]) { //C2027
a.memorie_RAM = memorie;
strcpy(b.denumire_procesor, denumire); //C2027
}
};
int main() {
Calculator a;
PlacadeBaza b;
int memorie;
char denumire[100];
cin >> memorie >> denumire;
b.set(a, b, memorie, denumire);
cout << a.getMemorie_RAM();
cout << b.getDenumire();
}
I am typing the following code and I am getting the following error at line-1
[Error] no matching function for call to 'int_adder::add()
#include <iostream>
using namespace std;
class adder{
public:
void add(){ cout <<"adder::add() "; }
};
class int_adder : public adder{
public:
int add(int a, int b){
return (a + b);
}
};
int main(){
int_adder ia;
ia.add(); //LINE-1
cout << ia.add(10, 20); //LINE-2
return 0;
}
As pointed by others in the comment, I have corrected it:-
#include <iostream>
using namespace std;
class adder{
public:
void add(){ cout <<"adder::add() "; }
};
class int_adder : public adder{
public:
int add(int a, int b){
return (a + b);
}
};
int main(){
int_adder ia;
ia.adder::add(); //LINE-1
cout << ia.add(10, 20); //LINE-2
return 0;
}
The statement adder::add() will overide the function add() present in int_adder.
Can't fing exact dupe, but you can make overloads from base class visible by using using directive, example:
#include <iostream>
using namespace std;
class adder{
public:
void add(){ cout <<"adder::add() "; }
};
class int_adder : public adder{
public:
using adder::add; // expose base class overload as our own
int add(int a, int b){
return (a + b);
}
};
int main(){
int_adder ia;
ia.add(); //LINE-1
ia.adder::add(); // explicit name also works
cout << ia.add(10, 20); //LINE-2
return 0;
}
As the other answer mentions using base class name scope also works. It all depends on your needs and class design.
Basically defining an overload in a derived class prevents implicit method look up from matching base class overloads, so you have to be explicit about it in one way or another.
You have totally two different versions of add in the first place. You are not overriding, you are overloading. You are just providing a new add function that has nothing to do with the other add function of the parent.
So first of all, do you want to override or overload?
Overriding the parent add would like the following:
#include <iostream>
using namespace std;
class adder{
public:
void add(){ cout <<"adder::add() "; }
};
class int_adder : public adder{
public:
int add() override {cout <<"int_adder ::add() ";};
int add(int a, int b){
return (a + b);
}
};
int main(){
int_adder ia;
ia.adder::add(); //LINE-1 <- would work displays adder::add()'s message
cout << ia.add(10, 20); //LINE-2
adder ia = int_adder{}; // now this is interesting
ia.add(); // would work displays adder::add()'s message - cause you did not ask for virtuality
return 0;
}
I just noticed something when creating functions. In the code:
#include <iostream>
using namespace std;
int add(int a, int b = 20)
{
int r;
r = a + b;
return (r);
}
int main()
{
int result;
result = add(20);
cout<<result;
return 0;
}
it will work because the function being called is on top of the caller, but if I put the function add() below the calling function in main() it won't work.
#include <iostream>
using namespace std;
int main()
{
int result;
result = add(20);
cout<<result;
return 0;
}
int add(int a, int b = 20)
{
int r;
r = a + b;
return (r);
}
and the compiler will tell me that the identifier add() cannot be found.
so why do we declare functions anyway? like this:
#include <iostream>
using namespace std;
int add(int a, int b = 20);
int main()
{
int result;
result = add(20);
cout<<result;
return 0;
}
int add(int a, int b)
{
int r;
r = a + b;
return (r);
}
A definition is implicitly a declaration. And a declaration must come ahead of the use.
All functions need to be declared before they are used.
You can do that by either (1) writing a declaration, or (2) writing a definition.
Relying solely on (2) can be tempting but then you are bound to order your program in a particular way, and is occasionally impossible. For example, the following will not compile unless the comment is removed.
//void bar(int);
void foo(int n)
{
if (!n){
bar(n);
}
}
void bar(int n)
if (n){
foo(n);
}
}
int main()
{
foo(1);
}
No.
If the function definition appears before the function call, then prototype is not mandatory. Otherwise function prototype is necessary to let compiler know how to respond to a function when it is called.
A function declaration tells the compiler about a function's name, return type, and parameters. A function definition provides the actual body of the function.
if the function definition appears after the function call then prototype is mandatory. because it tells the compiler to how to respond the function when it is called.
check the following example.
/* C++ Function Prototype and C++ Function Definition */
#include<iostream.h>
#include<conio.h>
#include<stdlib.h>
int add(int, int); // function prototype
void main()
{
clrscr();
int a, b;
cout<<"Enter any two number: ";
cin>>a>>b;
cout<<"\nSummation = "<<add(a, b);
getch();
}
int add(int x, int y) // function definition
{
int res;
res = x + y;
return res;
}
and if the function definition is made before the function call then it is not mandatory to declare function prototype.
consider example.
/* C++ Function Prototype and C++ Function Definition */
#include<iostream.h>
#include<conio.h>
#include<stdlib.h>
int add(int x, int y) // function definition
{
int res;
res = x + y;
return res;
}
void main()
{
clrscr();
int a, b;
cout<<"Enter any two number: ";
cin>>a>>b;
cout<<"\nSummation = "<<add(a, b);
getch();
}
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
#include <iostream>
using namespace std;
class B
{
public:
int getMsg(int i)
{
return i + 1;
}
};
class A
{
B b;
public:
void run()
{
taunt(b.getMsg);
}
void taunt(int (*msg)(int))
{
cout << (*msg)(1) << endl;
}
};
int main()
{
A a;
a.run();
}
The above code has a class B inside a class A, and class A has a method taunt that takes a function as an argument. class B's getMsg is passed into taunt...The above code generated the following error message: "error: no matching function for call to 'A::taunt()'"
What's causing the error message in the above code? Am I missing something?
Update:
#include <iostream>
using namespace std;
class B
{
public:
int getMsg(int i)
{
return i + 1;
}
};
class A
{
B b;
public:
void run()
{
taunt(b.getMsg);
}
void taunt(int (B::*msg)(int))
{
cout << (*msg)(1) << endl;
}
};
int main()
{
A a;
a.run();
}
t.cpp: In member function 'void A::run()':
Line 19: error: no matching function for call to 'A::taunt()'
compilation terminated due to -Wfatal-errors.
I'm still getting the same error after changing (*msg)(int) to (B::*msg)(int)
b.getMsg is not the correct way to form a pointer to member, you need &B::getMsg.
(*msg)(1) is not the correct way to call a function through a pointer to member you need to specify an object to call the function on, e.g. (using a temporary) (B().*msg)(1).
The right way to do such things in OOP is to use interfaces so all you need to do is to define an interface and implement it in B class after that pass the pointer of instance which implements this interface to your method in class A.
class IB{
public:
virtual void doSomething()=0;
};
class B: public IB{
public:
virtual void doSomething(){...}
};
class A{
public:
void doSomethingWithB(IB* b){b->doSomething();}
};
This works in VS 2010. The output is the same on all lines:
#include <iostream>
#include <memory>
#include <functional>
using namespace std;
using namespace std::placeholders;
class A
{
public:
int foo(int a, float b)
{
return int(a*b);
}
};
int main(int argc, char* argv[])
{
A temp;
int x = 5;
float y = 3.5;
auto a = std::mem_fn(&A::foo);
cout << a(&temp, x, y) << endl;
auto b = std::bind(a, &temp, x, y);
cout << b() << endl;
auto c = std::bind(std::mem_fn(&A::foo), &temp, _1, y);
cout << c(5) << endl;
}
Basically, you use std::mem_fn to get your callable object for the member function, and then std::bind if you want to bind additional parameters, including the object pointer itself. I'm pretty sure there's a way to use std::ref to encapsulate a reference to the object too if you'd prefer that. I also included the _1 forwarding marker just for another way to specify some parameters in the bind, but not others. You could even specify everything BUT the class instance if you wanted the same parameters to everything but have it work on different objects. Up to you.
If you'd rather use boost::bind it recognizes member functions and you can just put it all on one line a bit to be a bit shorter: auto e = boost::bind(&A::foo, &temp, x, y) but obviously it's not much more to use completely std C++11 calls either.