The code snippet below produces an error:
#include <iostream>
using namespace std;
class A
{
public:
virtual void print() = 0;
};
void test(A x) // ERROR: Abstract class cannot be a parameter type
{
cout << "Hello" << endl;
}
Is there a solution/workaround for this error other/better than replacing
virtual void print() = 0;
with
virtual void print() = { }
EDIT: I want to be able to pass any class extending/implementing the base class A as parameter by using polymorphism (i.e. A* x = new B() ; test(x); )
Cheers
Since you cannot instantiate an abstract class, passing one by value is almost certainly an error; you need to pass it by pointer or by reference:
void test(A& x) ...
or
void test(A* x) ...
Passing by value will result in object slicing, with is nearly guaranteed to have unexpected (in a bad way) consequences, so the compiler flags it as an error.
Of course, change the signature:
void test(A& x)
//or
void test(const A& x)
//or
void test(A* x)
The reason your version doesn't work is because an object of type A doesn't logically make sense. It's abstract. Passing a reference or pointer goes around this because the actual type passed as parameter is not A, but an implementing class of A (derived concrete class).
To be absolutely clear, the problem is, whenever you define a class:
#include <iostream>
class foo {
public:
char *name = (char *)"foo";
};
and pass an instance of that class to a function, it creates a copy:
void bar(foo a) {
a.name = (char *)"bar";
}
int main() {
foo x;
bar(x);
std::cout << x.name << std::endl; // foo
return 0;
}
With regard to inheritance, it creates a copy as an instance of the base class:
#include <iostream>
class foo {
public:
char *name = (char *)"foo";
};
class bar: public foo {
public:
char *name = (char *)"bar";
};
void baz(foo a) {
std::cout << a.name << std::endl;
}
int main() {
bar x;
baz(x); // again, foo
return 0;
}
so, by doing
void baz(AbstractType a) {
...
}
you're telling the compiler to copy an AbstractType as an instance of AbstractType itself, which is illegal.
Pass it as const AbstractType &a to prevent copying.
Related
Following up my previous question about pointers to functions I'd like to ask, what is the difference between the pieces of code below.
This works! I use a pointer to a member function of the class Base. Though I have to call the function through the pointer differently cause it's a pointer to a member and not a pointer to a free function. But it works.
#include <iostream>
class Base;
using Handler = void (Base::*)(int e);
class Base
{
protected:
Base(Handler init)
{
currentState = init;
}
Handler currentState;
};
class Derived : public Base
{
public:
Derived() : Base((Handler)&foo)
{
}
void run(int e)
{
(this->*currentState)(e);
}
private:
void foo(int e)
{
std::cout << "foo function\n";
std::cout << "e = " << e << std::endl;
}
};
int main(void)
{
Derived derived;
derived.run(10);
return 0;
}
Output:
foo function
e = 10
Then I modify the code a little bit and I use pointer to function using Handler = void (*)(int e);
#include <iostream>
class Base;
using Handler = void (*)(int e);
class Base
{
protected:
Base(Handler init)
{
currentState = init;
}
Handler currentState;
};
class Derived : public Base
{
public:
Derived() : Base((Handler)&foo)
{
}
void run(int e)
{
currentState(e);
}
private:
void foo(int e)
{
std::cout << "foo function\n";
std::cout << "e = " << e << std::endl;
}
};
int main(void)
{
Derived derived;
derived.run(10);
return 0;
}
And it does not work, as you can see from the output below
Output:
foo function
e = 679096448
Also, Is that legal in C++? Or I have a piece of code that happens to work? I'm asking that because I'm making a state machine model and I wouldn't like surprises in the middle of development down the line...
EDIT: Adding one more question, Why does the function is called, but the argument value is unspecified?
I think you should use std::function and learn how to use lambdas or std::bind -- I prefer lambdas.
You can define something like this:
#include <functional>
using Comparator = std::function<bool(const MyObject &)>;
And then you can assign a lot of different things to it. You can define either free or static methods. You can use std::bind in order to assign non-static methods. Or you can do what I do, and use a lambda.
void foo(Comparator f) {
if (f(someObject)) {
....
}
}
That part is easy. You can call that like this (for instance):
foo([](const Myobject &obj) { return obj.foo == bar; });
Or:
foo([](const Myobject &obj) { return obj.gleep(); });
Function pointers are a C-ism. std::function is how to do it in C++. It's more powerful. It can do everything a function pointer can do, but it can go further.
I don't care for std::bind, but you can find examples. Lambda syntax isn't necessarily simple, either, but I prefer it.
Is it possible to pass this by default ?
Here is what I currently have
class A
{
public:
template<typename T>
void dowithT(T t) {}
};
class B
{
public:
A a;
B()
{
//Calling 'dowithT' with 'this'
a.dowithT(this);
}
};
This function requires passing this from the caller of the function every time. So I wondered if there is a way to encapsulate this task, so that you don't need to pass this to dowithT.
I tried to do something like this:
class A
{
public:
// '= this' doesn't compile
template<typename T>
void dowithT(T t = this) {}
};
class B
{
public:
A a;
B()
{
//Calling 'dowithT' without 'this'
a.dowithT();
}
};
Unfortunately, I can't use templates, so my first solution isn't an option.
Is this possible?
Edit: I gave a concrete answer with my own implementation below. Also with a few mor deatils of what I wanted in the end.
TL;DR No, this is not possible.
this is not the same type in every class, you can't generalize it, so no, not possible.
Additionally, what would this be if doWithT() was called from a non-member function? nullptr?
That's why it isn't possible. You have to use a template.
Instead of B having a member of type A, it can inherit from A, and use something like the "curiously recurring template pattern."
If you cannot make class A a template, you can still do it like so:
class A
{
protected:
template <class T>
void dowithT()
{
T* callerthis = static_cast<T*>(this);
// callerthis is the "this" pointer for the inheriting object
cout << "Foo";
}
};
class B : public A
{
public:
B()
{
dowithT<B>();
// Or A::dowithT<B>();
}
};
dowithT() must only be called by an inheriting class (hence I made it protected), with the template parameter the caller's own type, or you'll break everything.
You may achieve exactly what you want by using a private mixin class to provide the dowithT method that takes no arguments:
#include <iostream>
#include <typeinfo>
class A
{
public:
template<typename T>
void dowithT(T* t) {
std::cout << "Hello, World" << typeid(*t).name() << std::endl;
}
};
template<class Owner>
struct calls_a
{
void dowithT()
{
auto p = static_cast<Owner*>(this);
p->a.dowithT(p);
}
};
class B
: private calls_a<B>
{
friend calls_a<B>;
A a;
public:
B()
{
//Calling 'dowithT' with 'this'
dowithT();
}
};
int main()
{
B b;
}
No, it is not possible. There is nothing really special about this when used as an argument to a function taking T* (template or not), it's just a pointer like any other.
this A is different from this B. In your first code, this refers to the caller, while in the second this refers to the callee. Thus what you want to do isnt really possible.
Here's one possibility, which might, or might not suit your needs:
template<typename T>
class A
{
public:
A(T t) : t(t) {}
void dowithT()
{
cout << "Foo";
}
private:
T t;
};
class B
{
public:
A<B*> a;
B() : a(this)
{
a.dowithT();
}
};
You could use a private method in class B that acts as a relay, and use the constant nullptr as a special value for this, if you want to be able to pass other values:
class B
{
public:
A a;
B()
{
//Calling 'dowithT' with 'this'
innerdo();
}
private:
void innerdo(B *p = nullptr) {
if (p == nullptr) p = this;
a.dowithT(p);
}
};
If you only need to pass this it is even simpler
void innerdo() {
a.dowithT(this);
}
After trying out various things you mentioned, I'd like to give my answer/solution to the problem myself to clarify some details:
#include <iostream>
using namespace std;
#include <functional>
template <typename CallerType>
class AFunctionConstructor{
private:
virtual void abstr()
{}
public:
typedef void(CallerType::*CallerTypeFunc)();
function<void()>* constructFunction(CallerTypeFunc func)
{
CallerType* newMe = dynamic_cast<CallerType*> (this);
return new function<void()>(std::bind(func,newMe));
}
};
class A : public function<void()>
{
protected:
public:
A();
A(function<void()>* func) : function<void()>(*func)
{}
};
// now create ressource classes
// they provide functions to be called via an object of class A
class B : public AFunctionConstructor<B>
{
void foo()
{
cout << "Foo";
}
public:
A a;
B() : a(constructFunction(&B::foo)) {}
};
class C : public AFunctionConstructor < C >
{
void bar()
{
cout << "Bar";
}
public:
A a;
C() : a(constructFunction(&C::bar)) {}
};
int main()
{
B b;
C c;
b.a();
c.a();
cout << endl;
A* array[5];
array[0] = &b.a; //different functions with their ressources
array[1] = &c.a;
array[2] = &b.a;
array[3] = &c.a;
array[4] = &c.a;
for (int i = 0; i < 5; i++) //this usability i wanted to provide
{
(*(array[i]))();
}
getchar();
return 0;
}
Output :
FooBar
FooBarFooBarBar
This is as far as i can press it down concerning examples. But i guess this is unsafe code. I stumbled across possible other and simpler ways to achieve this (other uses of std::function and lambdas(which i might have tried to reinvent here partially it seems)).
At first I had tried to pass "this" to the bind function in function<void()>*AFunctionConstructor::constructFunction(CallerTypeFunc func)
,though, which i now get through the dynamic upcast.
Additionally the functionality of AFunctionConstructor was first supposed to be implemented in a Constructor of A.
For one class I want to store some function pointers to member functions of another class. I am trying to return a class member function pointer. Is it possibile?
class one{
public:
void x();
void y();
};
typedef void(one::*PF)(void);
class two :public one{
public:
virtual PF getOneMethodPointer();
};
class three : public two{
std::vector<PF> pointer_to_function;
PF getOneMethodPointer();
pointer_to_function.push_back(getOneMethodPointer())? //how to get method x from class one?
};
In C++11/14, you can always use std::function wrapper to avoid writing unreadable and old C-style function pointers. Here's a simple program with this approach:
#include <iostream>
#include <functional>
using namespace std;
class one {
public:
void x() { cout << "X called" << endl; }
function<void()> getOneMethodPointer();
};
class two : public one {
public:
function<void()> getOneMethodPointer() {
return bind(&one::x, this);
}
};
int main()
{
two* t = new two();
t->getOneMethodPointer()();
delete t;
return 0;
}
As you can see, there's also std::bind used to bind method with std::function. First argument is a reference to the x() method and the second one specifies to which concrete (instantiated) object the pointer is meant to point. Note, that if you say to the st::bind "hey, bind me x() method from one class", it still doesn't know where it is. It knows that - for instance - x() method in this object can be found 20 bytes next to its beginning. Only when you add that it is from for example two* t; object, the std::bind is able to locate the method.
EDIT: Answering to your questions in comments: below code shows an example with virtual getMethodPointer() method:
#include <iostream>
#include <functional>
using namespace std;
class one {
public:
void x() { cout << "X called (bound in one class)" << endl; }
void y() { cout << "Y called (bound in two class)" << endl; }
virtual function<void()> getMethodPointer() {
return bind(&one::x, this);
}
};
class two : public one {
public:
virtual function<void()> getMethodPointer() {
return bind(&one::y, this);
}
};
int main()
{
one* t_one = new one();
one* t_two = new two();
t_one->getMethodPointer()();
t_two->getMethodPointer()();
delete t_one;
delete t_two;
return 0;
}
The C++ syntax for it is this:
class two: public one{
virtual PF getOneMethodPointer(){
return &one::x;
}
};
[Live example]
Is it possible in C++?
For example I have a pointer to a function that takes no parameters and its return type is void:
void (*f)();
and and a function object:
class A
{
public:
void operator()() { cout << "functor\n"; }
};
Is it possible to assign to f the address of an A object? And when I call f() to call the A functor?
I tried this but it doesn't work:
#include <iostream>
using namespace std;
class A
{
public:
void operator()() { cout << "functorA\n"; }
};
int main()
{
A ob;
ob();
void (*f)();
f = &ob;
f(); // Call ob();
return 0;
}
I get C:\Users\iuliuh\QtTests\functor_test\main.cpp:15: error: C2440: '=' : cannot convert from 'A *' to 'void (__cdecl *)(void)'
There is no context in which this conversion is possible
Is there any way to achieve this?
You can't do it in the way you've specified, because:
operator() must be a nonstatic function (standards requirement)
a pointer to a non-static function must have an implicit parameter - the pointer to the class instance
your call to f() does not give any indication on which instance of the object A your function is called
Using C++11 and std::function, as Stephane Rolland pointed out, may do the trick - you'll be specifying the pointer to the object in the binding:
std::function<void(void)> f = std::bind(&A::operator(), &ob);
(See question on using std::function on member functions)
If you use C++11, could use std::function
#include <functional>
std::function<void()> f;
int main()
{
A ob;
ob();
f = ob; // f refers to ob
f(); // Call ob();
return 0;
}
Yes it's kind of possible using a C++1/C++0x feature, but to achieve this you should use the std::function which can address to the two types, functions and object functions.
#include <functional>
class A
{
public:
void operator()() { }
};
int main()
{
std::function<void(void)> aFunction;
A ob;
aFunction = ob;
// or as another user said
// aFunction = std::bind(&A:operator(), &ob);
aFunction();
void (*f)();
aFunction = f;
aFunction();
return 0;
}
and if you're stuck with C++03, you could play with std::mem_fun and std::ptr_fun
How about some workaround like this:
Basically you want to have a common way of calling member functions and functions. Then maybe you could create a wrapper that would represent a generic pointer to either a function or member function. Let's say you have Base class and you want to be able to invoke operator() of all derived classes. Then you also have a function() that you want to invoke as well:
class Base
{
public:
virtual void operator()() = 0;
};
class A : public Base
{
public:
void operator()(){ std::cout << "A()" << std::endl; }
};
void function()
{
std::cout << "function" << std::endl;
}
If you create an wrapper that allows you to construct your custom pointer (MyFncPtr):
typedef void (Base::*BaseFncPtr)();
typedef void (*FncPtr)();
class MyFncPtr
{
public:
MyFncPtr(FncPtr f) : fnc(f), baseObj(NULL), baseFnc(NULL) { }
MyFncPtr(BaseFncPtr fPtr, Base* objPtr) : baseFnc(fPtr), baseObj(objPtr), fnc(NULL) { }
void invoke()
{
if (baseObj && baseFnc)
(baseObj->*baseFnc)();
else if (fnc)
fnc();
}
private:
BaseFncPtr baseFnc;
Base* baseObj;
FncPtr fnc;
};
you could achieve it like this:
A a;
MyFncPtr myPtr(&Base::operator(), &a);
myPtr.invoke();
MyFncPtr myPtr2(function);
myPtr2.invoke();
outputs:
A()
function
Hope this helps :)
There is a class
class A {
public:
A() {};
private:
void func1(int) {};
void func2(int) {};
};
I want to add a function pointer which will be set in constructor and points to func1 or func2.
So I can call this pointer (as class member) from every class procedure and set this pointer in constructor.
How can I do it?
class A {
public:
A(bool b) : func_ptr_(b ? &A::func1 : &A::func2) {};
void func(int i) {this->*func_ptr(i);}
private:
typedef void (A::*func_ptr_t_)();
func_ptr_t_ func_ptr_;
void func1(int) {};
void func2(int) {};
};
That said, polymorphism might be a better way to do whatever you want to do with this.
Add a member variable
void (A::*ptr)();
set it in the constructor
ptr=&A::func1;
(or use the initializer list) and call it in methods of A:
(this->*ptr)();
I compiled and ran this code. The various members need to be public so you can pass them into the constructor. Otherwise, here you go.
However, I agree with other posters that this is almost definitely a bad thing to do. ;) Just make invoke pure virtual, and then make two subclasses of A which each override invoke().
#include <iostream>
using namespace std;
class A;
typedef void(A::*MyFunc)(int) ;
class A {
public:
A() {}
A(MyFunc fp): fp(fp) {}
void invoke(int a)
{
(this->*fp)(a);
}
void func1(int a) { cout << "func1 " << a << endl; }
void func2(int a) { cout << "func2 " << a << endl; }
private:
MyFunc fp;
};
int main()
{
A* a = new A( & A::func1 );
a->invoke(5);
A* b = new A( & A::func2 );
b->invoke(6);
}
See boost::function for a way to handle function and class member pointers in a more OO/C++ manner.
For example (from the documentation) :
struct X
{
int foo(int);
};
boost::function<int (X*, int)> f;
f = &X::foo;
X x;
f(&x, 5);
I suggest you use functor(or function object), rather than function pointer, because the former is safer, and function pointer can be difficult or awkward to pass a state into or out of the callback function
A functor is basically a re-implementation of operator() of class A, for very detailed description please refer to Wikipedia: http://en.wikipedia.org/wiki/Function_object
The code should be something like this:
class A {
public:
A() {};
void operator()(int function_index, int parameter) {
if(function_index == 1)
func1(parameter);
else if(function_index == 2)
func2(parameter);
else
{ //do your other handling operation
}
}
private:
void func1( int ) {};
void func2( int) {};
};
By using that class:
A a;
a(1, 123); //calling func1
a(2, 321); //calling func2
Why do you think it's a bad thing to do. I just need one function pointer and I don't want to create two subclasses for this. So why is it so bad?
Some example...
class A; // forward declaration
typedef void (A::*func_type)(int);
class A {
public:
A() {
func_ptr = &A::func1;
}
void test_call(int a) {
(this->*func_ptr)(a);
}
private:
func_type func_ptr;
void func1(int) {}
void func2(int) {}
};