I have three classes:
class ShapeEditor {}
class PointEditor: ShapeEditor{}
class RectEditor: ShapeEditor{}
I want to define a function pointer in Manager
class and pass it in constructor as lambda function. It looks like this:
class Manager {
public:
ShapeEditor (*factory)();
Manager(ShapeEditor (*_factory)());
}
Then I'm writing in main:
Manager m = Manager([] { return PointEditor(); }
and getting an error message that there is no constructor for this expression.
When I changes ShapeEditor
to PointEditor
in Manager
- it works fine, but I need to specify different types in function result.
@NathanOliver gave the correct answer in comments above:
Yes, but you didn't specify a return type for the lambda, so it gets it from the returned object, and that object doesn't have the same type as the return type your function pointer needs
So here is my solution:
Manager m = Manager([] -> ShapeEditor* { return new PointEditor(); });
Your problem is that your lambda returns object value of type ShapeEditor
which inherits from ShapeEditor
and base class value is expected.
Basically you are expecting some kind of polymorphism, but you return value of some specific child type when you expect value for base type! This leads to silent conversion and as a result behavior is different then you expect so your answer is incorrect.
If you need polymorphism you need use a pointer or reference:
#include <memory>
#include <string>
class ShapeEditor {
public:
virtual ~ShapeEditor() {}
virtual std::string doSomething() = 0;
};
class PointEditor: public ShapeEditor {
public:
std::string doSomething() override;
};
class RectEditor: public ShapeEditor{
public:
std::string doSomething() override;
};
using ShapeEditorPtr = std::unique_ptr<ShapeEditor>;
class Manager {
public:
ShapeEditorPtr (*factory)();
Manager(ShapeEditorPtr (*_factory)());
};
void test() {
Manager m = Manager([]() -> ShapeEditorPtr {
return std::make_unique<PointEditor>();
});
}
as I can see that your problem is to try casting a PointEditor
instance into a ShapeEditor
instance. You need to cast Pointers, instead of values. So, in your lambda expression, you are returning a COPY of local instance PointEditor
and trying to copy it into a ShapeEditor
local variable.
Here is my proposal:
#include <cmath>
#include <cstdio>
#include <map>
#include <iostream>
using namespace std;
class ShapeEditor {
public:
virtual void printName(){};
};
class PointEditor: ShapeEditor{
public:
void printName(){cout << "PointEditor\n";};
};
class RectEditor: ShapeEditor{
public:
void printName(){cout << "RectEditor\n";};
};
class Manager {
ShapeEditor* shp;
ShapeEditor* (*factory) ();
public:
Manager( ShapeEditor* (*_factory)() ):factory{_factory}{
shp = factory();
shp->printName();
};
~Manager(){delete shp;}
};
int main()
{
ShapeEditor* (*func1)() = [](){
PointEditor* x = new PointEditor();
ShapeEditor* s = (ShapeEditor*)x;
return s;
};
ShapeEditor* (*func2)() = [](){
RectEditor* x = new RectEditor();
ShapeEditor* s = (ShapeEditor*)x;
return s;
};
Manager m1 = Manager(func1);
Manager m2 = Manager(func2);
return 0;
}
the output:
PointEditor
RectEditor
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.