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.
Related
I have a class A which has a constructor with a function argument: i.e.
class A {
public:
A(int (*f)(int);
};
I can create this class and have it use func() with, for example,
int func(int n);
A a(func);
I would like to invoke this class a number of times, but have it use internally func(n)+m instead of func(n). I would prefer not to change class A. I could create a new class to define the function I want
class B {
int (*func)(int n);
int m;
public:
B(int (*ff)(int),int mm) : func(ff),m(mm) {}
int myfunc(int n) { return(func(n)+m);
};
However, I don't think it is possible to convert a pointer to myfunc into a pointer with the required signature for A's constructor.
The way I have chosen is similar to the above, but with myfunc() and associated variables stored in the global space:
int m;
int (*func)(int);
int myfunc(int n) { return(func(n)+m); }
void setupmyfunc(int mm,int (*ff)(int)) { m=mm; func=ff; }
Then I can can create my A object with
setupmyfunc(m,func);
A a(myfunc);
This works, but seems inelegant to me. Is there a better way?
Stateless lambdas are implicitly convertible to function pointers so you can just use that without modifying your class A and without creating another class B. That is if I understood your question correctly.
class A {
public:
A(int (*f)(int)) {};
};
int func(int n) { return n * 10; }
auto test()
{
A a{[](int n) { return func(n) + 1; }};
}
std::function can hold callable objects (functions, function objects, member function pointers (with object to bind to), etc. It uses some type-erasure such that it can have this genericity, but comes at the cost of internal overhead to actually invoke it, often equivalent to a virtual function call.
Here's an example, where A takes a std::function, which allows you to pass in lambdas.
#include <functional>
#include <iostream>
class A {
std::function<int(int)> func_;
public:
A(std::function<int(int)> func) : func_(func) {}
int call(int x) {
return func_(x);
}
};
int foo(int x) {
return x * 123; // whatever
}
int main() {
// here's your wrapper function to do func(x)+m (m==9 in this case)
A obj([](int x) { return foo(x) + 9; });
int result = obj.call(123);
std::cout << result << '\n';
}
https://godbolt.org/z/94MfGM67K
Update:
Given the rejection of both answers so far, using std::function is out because it changes class A, and the obvious use of state-full lambdas for composition and capturing customization data is also out, you will need to get more creative and possibly ugly. If you can't change A, then you can't change the signature of the function passed to a, so making the lambda take its data as another argument is also out.
Seems to me that leaves just one thing: using state that is outside the function (i.e. global data or encoded in a template non-type template parameter) as a form of pseudo-capture that an otherwise stateless function can use. I reject the global approach in general, though there's interesting aspects to it, and only present a template solution:
Now you write your free-standing functions and can compose them with a template:
#include <iostream>
using F = int(*)(int);
class A {
public:
A(F f) : f_(f) { }
int operator()(int x) { return f_(x); } // Added for demo
private:
F f_;
};
template <F FuncF, F FuncG>
int compose(int n) {
return FuncF(FuncG(n));
}
int func(int n) { return n * 1000; }
int add888(int n) { return n + 888; }
int add999(int n) { return n + 999; }
int main() {
A a1(compose<add888, func>);
A a2(compose<add999, func>);
std::cout << a1(1) << " " << a2(1) << " " << a1(1);
}
// output: 1888 1999 1888
https://godbolt.org/z/8KsqbTcTd
This works as far back as c++11, and replacing the "using" with "typedef" it work in C++98.
Member function declarations with the same name and the name parameter-type-list cannot be overloaded if any of them is a static member function declaration. For example, following program fails in compilation.
#include<iostream>
class Test {
static void fun(int i) {}
void fun(int i) {}
};
int main()
{
Test t;
getchar();
return 0;
}
I don't understand why the following example can run:
#include<iostream>
class Test {
public:
static void fun(double i) {
std::cout << i << "\n";
}
void fun(int i) {
std::cout << i;
}
};
int main()
{
Test t;
t.fun(5.5);
t.fun(4);
return 0;
}
The second Example will run because the parameter types are different in both the function, i.e. double in the first and int in second. So function overloading takes place
Function overloading only works when you have different set of parameters, in the example's case it's int and double. change the parameter data type.
Why are we able to call the showA() method without object? But if I use void A::showA(A& x) in the method definition then I have to call it using A's object, why?
#include <iostream>
class A {
public:
int a;
A() { a = 0; }
void showA(A&);
};
void showA(A& x)
{
std::cout << "A::a=" << x.a;
}
int main()
{
A a;
showA(a);
return 0;
}
Why are we able to call the showA() method without object?
You don't call the member function A::showA, but instead the free function showA. In fact, the member function A::showA(A&) is declared, but never defined, only the free function showA(A&) has a definition.
If you want to call A::showA, you need a definition;
void A::showA(A& x) { /* ... */ }
// ^^^ this makes it a member function definition
and then call it as
A a;
a.showA(a);
(Note that it doesn't make much sense to pass the a instance to A::showA invoked on the identical a instance, but that's another issue).
This function
void showA(A& x)
{
std::cout << "A::a=" << x.a;
}
is not a member function of the class A.
It accepts one argument of the type A &.
As for the member function showA then it is declared but not defined.
You could declare it within the class like
class A {
public:
int a;
A() { a = 0; }
void showA() const;
};
and then define it outside the class definition like
void A::showA() const
{
std::cout << "A::a=" << a;
}
In this case the function main can look like
int main()
{
A a;
showA(a);
a.showA();
return 0;
}
You can't call it because showA(the one you are thinking) is not the part of the class.It is a global function.The showA function which you declared in class was never defined. In order to do so modify your code a bit.
Change this piece of code.
void A::showA(const A& x) {
std::cout << "A::a=" << x.a; } // It is advised to make const as it doesn't change state.
I am trying to build a class that has a member function with a method as argument. The methods are defined in inherited classes. I build a minimal example:
#include <iostream>
struct base
{
base() {}
int number(int (*f)(int))
{
return f(1);
}
};
struct option1 : base
{
int timesTwo(int i){return 2*i;}
option1()
{
std::cout << number(timesTwo);
}
};
struct option2 : base
{
int timesThree(int i){return 3*i;}
int timesFour (int i){return 4*i;}
option2()
{
std::cout << number(timesThree);
}
};
int main()
{
option1 a; //I would expect this to print "2"
}
The current syntax in the function number is for a general function, but I cannot get it to work for a method of any inherited classes.
The problem here is that you're passing a pointer to a member function, which is completely different from a pointer to a non-member function (which is what your number function takes as an argument).
You could use std::function and std::bind:
int number(std::function<int(int)> f)
{
return f(1);
}
...
number(std::bind(&option1::timesTwo, this, _1));
You could also use templates, and extra arguments, like
template<typename T>
int number(T* object, int(T::*f)(int))
{
return (object->*f)(1);
}
...
number(this, &option1::timesTwo);
Or the simple (but not always correct, depending on situation and use case): Make the callback-function static:
static int timesTwo(int i){return 2*i;}
My recommendation is that you look over the solution using std::function, because then it's easy to call the number function with any type of callable object, like a lambda:
number([](int x){ return x * 2; });
The given error says :
error: reference to non-static member function must be called
You can just add static before your method members.
And I would suggest you to use std::function instead of pointer functions.
A working code :
#include <iostream>
#include <functional>
struct base
{
base() {}
int number(std::function<int(int)> f)
{
return f(1);
}
};
struct option1 : base
{
static int timesTwo(int i){return 2*i;}
option1()
{
std::cout << number(timesTwo);
}
};
struct option2 : base
{
static int timesThree(int i){return 3*i;}
static int timesFour (int i){return 4*i;}
option2()
{
std::cout << number(timesThree);
}
};
int main()
{
option1 a; // now it works
}
I have a class(A) that contains for example five variables (parameters t,z,y,d and f) and I created an object(A) of a type class(A). Then I have many functions (X,U,M) that are included in the "main.cpp", each function is defined to take only three or four parameters that are already exist in the object(A). for example function(X) uses the variables (t,y and z only)
Instead of passing the parameters as void function(X) (int t, int y, double z){} can I pass only the object(A) and let each function selects its parameters by just looking for what it needs from object(A)'s parameters as follow (if this exist)?
void function(X) (A()){}
I would like to avoid using the following.
void function(X) (A.t, A.y, A.z){}
(Please note I am new to c++ and I am working in Qt Creator.)
Yes, you can pass an object to a function. There are several ways to pass the an instance of a class to a function:
by value (if function() needs to modify obj but the caller does not need to see the changes and copying is inexpensive):
void function(A obj) {}
by reference (if function() modifies obj and changes must be visible to the caller):
void function(A& obj) {}
by const reference (if function() does not modify obj):
void function(A const& obj) {}
by rvalue reference (c++11):
void function(A&& obj) {}
The class A will need to provide access to it's members.
Easy
class A
{
public:
double z;
};
void func(const A &obj)
{
// Do something with obj.z
std::cout << obj.z << std::endl;
}
int main()
{
A myObj;
myObj.z = 100;
func(myObj);
}
Joachim's explanation is what you need, except that the object should be passed as either a pointer or a reference, to ensure it isn't getting copied.
void someFunction(C& c)
// Accept a reference to a 'C' object
{
// Joachim's code
// This method doesn't change the main from Joachim's
// answer.
}
void someFunction(C* c)
// Accept a pointer to a 'C' object
{
std::cout << "The member i_ is " << c->getI() << std::endl;
// Note the use of '->', not '.' to access the object's method.
}
void main()
{
C c;
c.setI(1);
someFunction(&c);
// The '&' means 'address of' in this context. I.E. you're passing a pointer.
}
If the member fields are public you can access them from any function. If the are not public you have to add member functions to the class to get the values, so called "getter" functions.
#include <iostream>
class C
{
public:
int getI() const { return i_; }
void setI(const int i) { i_ = i; }
private:
int i_;
}
void someFunction(C c)
{
std::cout << "The member i_ in c is " << c.getI() << '\n';
}
int main()
{
C c;
c.setI(123);
someFunction(c);
}