I wonder how dynamic dispatching really works in C++. To illustrate my question, I will start by some Java code.
class A
{
public void op(int x, double y) { System.out.println("a"); }
public void op(double x, double y) { System.out.println("b"); }
}
class B extends A
{
public void op(int x, double y) { System.out.println("c"); }
public void op(int x, int y) { System.out.println("d"); }
}
class C extends B
{
public void op(int x, int y) { System.out.println("e"); }
}
public class Pol
{
public static void main(String[] args)
{
A a = new C();
B b = new C();
/* 1 */ a.op(2, 4);
/* 2 */ b.op(2.0, 4.0);
}
}
The call a.op(2, 4) will print "c", since indeed the compiler:
looks into Class A (since a is declared to be a variable of type A) which method is the closest to op(int, int),
can't find a op(int, int) method but finds the method op(int, double) (with a single auto-cast int -> double),
then fixes this signature.
During the execution, the JVM:
looks for a method with the signature op(int, double) fixed by the compiler into Class C but doesn't find it,
looks inside C's super-class, i.e., B,
and finally finds a method op(int, double), then calls it.
The same principle applies to the call b.op(2.0, 4.0), which prints "b".
Now, consider the equivalent code in C++
#include <iostream>
class A
{
public:
virtual void op(int x, double y) { std::cout << "a" << std::endl; }
virtual void op(double x, double y) { std::cout << "b" << std::endl; }
};
class B : public A
{
public:
void op(int x, double y) { std::cout << "c" << std::endl; }
virtual void op(int x, int y) { std::cout << "d" << std::endl; }
};
class C : public B
{
public:
void op(int x, int y) { std::cout << "e" << std::endl; }
};
int main()
{
A *a = new C;
B *b = new C;
/* 1 */ a->op(2, 4);
/* 2 */ b->op(2.0, 4.0);
delete a;
delete b;
}
a->op(2, 4) will print "c", like Java. But b->op(2.0, 4.0) outputs "c" again, and there, I'm lost.
What are exactly the rules applied at the compilation and during the execution in C++ for dynamic dispatching?
(Notice you will have the same behavior from the C++ code if you write virtual in front of each function; it changes nothing here)
For C++, when you do b->op(2.0, 4.0); the compiler looks in B, finds a method it can call (int x, double y) and uses it. It does not look in the superclass if any method in the subclass can handle the call. This is called method hiding, ie. op(double, double) is hidden.
If you want to make it select the (double x, double y) version, you need to make the function visible inside of B with the following declaration inside B:
using A::op;
Further explanation of the rules
By declaring a new overload to op in B you have hidden the base versions. The compiler will only dispatch based on 'B' which is why it selects op(int,double).
The compiler will warn/error on conversions if you tell it to. Using gcc, the compiler arguments -Wconversion -Werror will prevent your code from compiling, as you are right, there is a potential loss in precision here.
Given that you didn't turn on this compiler option, the compiler is happy to resolve your call to b->op(double, double) to B::op(int, double).
Please keep in mind that this is a compile time decision - not a runtime/polymorphic decision.
The actual vtable of the "b" pointer will have a method op(int, int) available at runtime, but the compiler doesn't know about this method at compile time. It only can assume that the b pointer is of type B*.
You start with the polymorphic behavior in your base class A. Then, using the same signature, you cannot stop this in the derived classes.
It's not necessary, if you declare the same method virtual or not.
You have to change the signature!
Furthermore, you have the visibility problem. This line
B *b = new C;
b->op(2.0, 4.0);
The compiler looks for a method within your class B. The op-methods hide the methods with the same name of class A (overload resolution). If he founds something useful, he is just using it.
Related
I have a code similar to the minimal example below, where the function g is provided by a library and expects double (*)(double) as an argument. I cannot change this. The example code does not compile because the member has signature double (*C::)(double) as explained in e.g. this post, with a number of possible solutions.
#include <iostream>
double g(double (*f)(double x)) { return f(0); };
class C
{
public:
C(double b) { a = b; };
double f2() { return g(&f1); };
private:
double a;
double f1(double x) { return x + a; };
};
int main()
{
C c (1);
std::cout << c.f2() << std::endl;
return 0;
}
I wonder what the best way to implement this is given that I don't want to point to C::f1 outside the class but within another member function. As far as I understand, the member function C::f1 is not static since it is only fully known after an instance of the class is initialised. Since speed is also a concern: would this be a problem with any of the possible solutions proposed elsewhere for similar versions of this issue?
Make your f1 function static:
static double f1(double x) { return x + a; };
This gives it the same signature as what your g function expects. Since a static function does not have a hidden this pointer, you will have to find some other way to get the value of a into it.
Okay, based on the comments and ideas from the post mentioned before, I will suggest to change g as follows and add a wrapper function f2_wrapper.
#include <iostream>
double g(double (*f)(double x, void *context), void *context)
{
return f(0, context);
};
class C
{
public:
C(double b) { a = b; };
double f1(double x) { return x + a; };
double f2();
private:
double a;
};
double f2_wrapper(double x, void* context)
{
C *c = (C*) context;
return c->f1(x);
}
double C::f2() { return g(&f2_wrapper, this); }
int main()
{
C c (1);
std::cout << c.f2() << std::endl;
return 0;
}
This question already has an answer here:
Inheritance and method overloading
(1 answer)
Closed 6 years ago.
This is my code
class B {
public:
virtual void insert(int t, int p) = 0;
void insert(int t) {
insert(t, 0);
}
};
class D : public B {
public:
void insert(int t, int p) { }
};
int main() {
D d;
d.insert(1);
}
which won't compile. Sure, it will if I say d.B::insert(1) in main, but why is this incorrect as is? Thanks.
This is because in this case base class functions are not included in overload resolution. Similar situation is with functions declared in inner scope - they do not overload functions declared in outer scope (see examples below). You can imagine that derived class scope is nested inside base class scope.
Once compiler has found D::insert candidate it will not look further in base class. If there were no D::insert then compiler will look into base class for insert method to call. You can fix this by introducing insert function names from base class with:
using B::insert;
this will introduce all the B::insert overloaded functions in derived class. Or as you say, you can explicitly call base class method with:
d.B::insert(1)
Sample code to how overloading works in the same way in other contexts:
namespace Outer {
void foo(double d) {
std::cout << "Outer::foo(double d)\n";
}
namespace Inner {
//using Outer::foo; // uncomment to see "Outer::foo(double d)" in output
void foo(int n) {
std::cout << "Inner::foo(int n)\n";
}
void callMe() {
foo(1.1);
}
}
}
int main() {
Outer::Inner::callMe(); // Outputes: Inner::foo(int n)
}
or:
void foo(std::string s) {
std::cout << "foo(std::string s)\n";
}
void foo(double d) {
std::cout << "foo(double d)\n";
}
void foo(int n) {
std::cout << "foo(int n)\n";
}
int main() {
void foo(int d); // comment out to see foo(double d) in output
foo(1.1); // outputs: "foo(int n)", foo(double d) is hidden
//foo("hello"); // ups, it wont compile - name lookup in c++ happens before type checking
// commenting out `void foo(int d);` above will fix this.
}
I'm pretty sure it's because you redefined the function "insert" in D, which is the one that gets called. The function "insert" in the class "D" requires two parameters instead of one. By doing d.B::insert(1), you're calling "insert" in B.
I want to write an object-oriented wrapper around old C-style functions, while keeping the actual function names the same. Take a look at an example:
#include <iostream>
void doStuff(int a, float b)
{
std::cout << "a = " << a << ", b = " << b << "\n";
}
class Stuff
{
private:
int a;
float b;
public:
Stuff(int newA, float newB) : a(newA), b(newB) { }
int getA() { return a; }
float getB() { return b; }
};
class Widget
{
public:
void doStuff(Stuff s)
{
doStuff(s.getA(), s.getB()); //error: no matching function for call to 'Widget::doStuff(int, float)'
}
};
int main()
{
Widget w;
w.doStuff(Stuff(42, 3.14f));
return 0;
}
In this example, void doStuff(int a, float b) is the old C-function. Because in my real code, its equivalent is in an external library/header file, I cannot change its name. Next, Stuff is a container for keeping the values void doStuff(int a, float b) needs. The important things happen in Widget: void Widget::doStuff(Stuff s) should be the actual wrapper. I now expect doStuff(s.getA(), s.getB()) to call the old C-style function void doStuff(int a, int b) but the compilation fails with the given error.
Is it possible to make this code work without changing the name of the both doStuff functions? One option I already thought of is surrounding void doStuff(int a, float b) by some namespace. This works, but seems like very bad practice to me.
My compiler is mingw-w64 with g++ 5.2.0, so C++11 and C++14 are available.
The doStuff(Stuff s) method in your class hides the global function doStuff(int a, float b). If you want to call the global doStuff function, you have to use the scope resolution operator :: (::doStuff(s.getA(), s.getB());)
Try making your call like this:
::doStuff(s.getA(), s.getB());
I have two functions that do the same thing: they add two numbers. One adds two numbers which are members of the class, the other adds numbers given by the user, outside the class.
Is there any way to write one single function that adds two numbers and checks whether the arguments are user input or class members?
void myclass::add(){
cout<<this->a+this->b;
}
void myclass::add(int a,int b){
cout<<a+b;
}
While you cannot really do it in a single function the common approach would be to write the more flexible of the two and use the other one just as a dispatcher:
void myclass::add(int a, int b) {
std::cout << (a+b);
}
void myclass::add() {
add(a,b);
}
Now, there are a different number of smells in this code... a function name reused to act on members or only inputs is one (a function that does not touch the object's state already smells at it not being a member, or being a static one). Printing inside a function called add (should it not return the values?)...
Disclaimer : I don't encourage such coding.
Ok, here's a method
void myClass::Add(int& a, int& b)
{
if (&a==&this->a)
{
std::cout << this->a + this->b
} else {
std::cout << a+b;
}
}
Ofc , things like myClass->Add(10,4) won't work... you will need some stack variables to hold the 10 and 4 variables.
So you want a single function that can have two different parameters? It isn't possible.
void myclass::add(int a, int b)
{
cout << a + b << endl;
}
Is what you want; but you can overload the function:
void myclass::add()
{
cout << memberA + memberB << endl;
}
In my opinion, this is a much better solution than having a single function that checks whether the variables are members or not; it makes your code readable. Don't be afraid to overload functions - it's one of those things that makes C++ awesome. I've created a class to demonstrate this:
class myClass
{
public:
myClass() : memberA(0), memberB(0) {}
~myClass() {}
void setNumbers(int a, int b)
{
memberA = a;
memberB = b;
}
void add(int a, int b)
{
cout << a + b << endl;
}
void add()
{
cout << memberA + memberB << endl;
}
private:
int memberA;
int memberB;
};
int main()
{
myClass m;
m.setNumbers(1, 2);
m.add();
return 0;
}
I've tested the add function with and without parameters and they both output the same result. The former because I used a setNumbers(..) function. Effectively, your first scenario of having two functions is the most apt solution to begin with.
In you realy wanted a single function, the way to do it is with optional default parameters.
Your declaration will be
void add(optional<int> a = optional<int>(), optional<int> b = optional<int>() );
Then in your implementation:
a ? a.get() : this->a
A benefit of this approach is that you can mix members and parameters. For example:
obj.add(1);
obj.add(optional<int>(), 2);
I'm trying to setup a function pointer that is set during execution based on a set of user parameters. I would like to have the function pointer point to a non-static member function but I can't find how to do it.
The examples I've seen say this can only be done with static member function only or use global variables in straight C.
A simplified example follows:
class CA
{
public:
CA(void) {};
~CA(void) {};
void setA(double x) {a = x; };
void setB(double x) {b = x; };
double getA(const double x) {return x*a; };
double getB(const double x) {return x*b; };
void print(double f(const double), double x) {
char cTemp[256];
sprintf_s(cTemp, "Value = %f", f(x));
std::cout << cTemp;
};
private:
double a, b;
};
The implementation part is
CA cA;
cA.setA(1.0);
cA.setB(2.0);
double (*p)(const double);
if(true) {
p = &cA.getA; //'&' : illegal operation on bound member function expression
} else {
p = cA.getB; //'CA::getB': function call missing argument list; use '&CA::getB' to create a pointer to member
//'=' : cannot convert from 'double (__thiscall CA::* )(const double)' to 'double (__cdecl *)(const double)'
}
cA.print(p, 3.0);
So how do I get p to point to either 'getA' or 'getB' so that it is still useable by 'print'.
From what I have seen, the suggestions are to use boost or std::bind but I've had no experience with either of these. I'm hoping that I don't need to dive into these and that I'm just missing something.
Compiler MSVC++ 2008
Don't forget that a member function accepts an implicit this parameter: therefore, a member function accepting a double can't be the same thing as a non-member (free) function accepting a double.
// OK for global functions
double (*p)(const double);
// OK for member functions
double (CA:*p)(const double);
Also the way you invoke them is different. First of all, with member functions, you need an object to invoke them on (its address will eventually be bound to the this pointer in the function call). Second, you need to use the .* operator (or the ->* operator if you are performing the call through a pointer):
p = &CA::getA;
CA cA;
(cA.*p)();
Consistently, you will have to change your definition of function print():
#include <iostream>
void print(double (CA::*f)(const double), double x)
{
// Rather use the C++ I/O Library if you can...
std::cout << "Value = " << (this->*f)(x);
};
So finally, this is how you should rewrite your main() function:
int main()
{
CA cA;
cA.setA(1.0);
cA.setB(2.0);
double (CA::*p)(const double);
if (true) // Maybe use some more exciting condition :-)
{
p = &CA::getA;
}
else {
p = &CA::getB;
}
cA.print(p, 3.0);
}
Compilation Issue
This answer focuses on the compilation issue presented in the question. I would not recommend implementing this as a solution.
Pointers to member functions are best dealt with with typedefs and a macro.
Here's the macro for calling a member function:
#define CALL_MEMBER_FN(object, ptrToMember) ((object).*(ptrToMember))
Source: [33.6] How can I avoid syntax errors when calling a member function using a pointer-to-member-function?, C++ FAQ.
This saves you having to remember the ugly (object).*(ptrToMember) syntax any time you wish to call a member function by pointer.
In your class, declare a typedef called CAGetter, this will make variable declaration much simpler:
class CA
{
public:
typedef double (CA::*CAGetter)(const double x);
Then you can declare your print() function quite simply:
void print(CAGetter f, double x)
The body is also simple, clear and concise:
{
std::cout << "value = " << CALL_MEMBER_FN(*this, f)(x) << '\n';
}
Sample usage:
CA a;
a.setA(3.1);
a.setB(4.2);
// Using a variable...
CA::CAGetter p = &CA::getA;
a.print(p, 1);
// without a variable
a.print(&CA::getB, 1);
// Calling the functions from outside the class...
std::cout << "From outside (A): " << CALL_MEMBER_FN(a, p)(10) << std::endl;
std::cout << "From outside (B): " << CALL_MEMBER_FN(a, &CA::getB)(10) << std::endl;
Design Issue
Passing a pointer to a member function into a method of an instance of the same class is a design smell (you wouldn't normally pass a member variable to a method, this is no different). There is not enough information in this question to address the underlying design issue but this problem could probably be solved with separate print() methods, a member variable or with inheritance and polymorphism.
You can either use pointer to method:
class CA
{
public:
typedef double (CA::*getter)( double );
CA(void) {};
~CA(void) {};
void setA(double x) {a = x; };
void setB(double x) {b = x; };
double getA(const double x) {return x*a; };
double getB(const double x) {return x*b; };
void print(getter f, double x) {
char cTemp[256];
sprintf(cTemp, "Value = %f", (this->*f)(x));
std::cout << cTemp;
};
private:
double a, b;
};
int main()
{
CA cA;
cA.setA(1.0);
cA.setB(2.0);
CA::getter p;
if(true) {
p = &CA::getA;
} else {
p = &CA::getB;
cA.print( p, 3.0 );
}
Or use boost::bind
class CA
{
public:
typedef boost::function<double( double )> getter;
CA(void) {};
~CA(void) {};
void setA(double x) {a = x; };
void setB(double x) {b = x; };
double getA(const double x) {return x*a; };
double getB(const double x) {return x*b; };
void print(getter f, double x) {
char cTemp[256];
sprintf(cTemp, "Value = %f", f(x));
std::cout << cTemp;
};
private:
double a, b;
};
int main()
{
CA cA;
cA.setA(1.0);
cA.setB(2.0);
CA::getter p;
if(true) {
p = boost::bind( &CA::getA, &cA, _1 );
} else {
p = boost::bind( &CA::getB, &cA, _1 );
}
cA.print( p, 3.0 );
}