Why are overloaded inherited static functions ambiguous? - c++

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;
}

Related

Static variable inside a template base class

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

Why can't a static data member has the same name with non-static data member?

#include<stdio.h>
#include<vector>
#include<iostream>
using namespace std;
int x = 1;
class foo
{
public:
foo()
{
x = 3;
}
static int x;
void bar() const
{
cout << x << endl;
}
int x;
};
int foo::x = 2;
int main()
{
cout << "Hello, world!" << endl;
return 0;
}
here's the compiler output:
test.cc:19:9: error: ‘int foo::x’ conflicts with a previous declaration
int x;
^
test.cc:14:16: note: previous declaration ‘int foo::x’
static int x;
They can't have the same name because which one would you mean when you refer to x in a non-static method?
The language designers could have decided to allow it, e.g. to prefer the non-static one or the reverse. But personally I'm glad they didn't.

Passing member function as parameter to another function in c++

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.

C++ Initilaztion of Vector of Classes

I have a Class
class MAC {
private :
int mac_address;
public:
int mac_access;
MAC() {mac_address = 10;}
MAC(int m_add,int m_axs):mac_address(m_add),mac_access(mac_access) {};
};
And I want to create vectors of this class and have the initialization like this
int main()
{
C m_c;
std::cout<<m_c.m_a.a << std::endl;
MAC a(9,3),b(4,5);
std::vector<MAC> m_arr;
m_arr(4,5);
}
When I compile I get this error
constructor.cpp: In function ‘int main()’:
constructor.cpp:63:12: error: no match for call to ‘(std::vector<MAC>) (int, int)’
Basically I am confused how can I give most of the function which a vector of int or char gives?
To clear the confusion I want my class to behave same as when we do something like this
std::vector<int> a (4,100);
but currently I cant do
std::vector<MAC> m_mac(4,100);
class MAC {
private :
int mac_address;
public:
int mac_access;
MAC(int arg_mac_address = 10):mac_address(arg_mac_address){}
MAC(int m_add,int m_axs):mac_address(m_add),mac_access(mac_access) {};
};
int main()
{
/*C m_c;
std::cout<<m_c.m_a.a << std::endl;*/
MAC a(9,3),b(4,5);
std::vector<MAC> m_arr(4, 5);
}

C++ : unresolved overloaded function when using function pointers

#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.