following problem:
I want to build a function which returns me a Pointer to an derived object from an abstract class. I think, the memory is freed when the function is left because i get an alloc-error. But i can't give the object back, because the class is abstract. In the function i decide, which derived class the object will be have. How can I solve the problem?
Any idea?
QgsSymbolV2* QGISFunc::ReadClassSymbolsXML(QString FeatureType, QXmlStreamReader &reader)
{
QgsMarkerSymbolV2* p_mlmSymbol=0;
try
{
QgsLineSymbolV2 mllSymbol;
QgsFillSymbolV2 mlfSymbol;
QgsMarkerSymbolV2 mlmSymbol;
...
return &mlmSymbol; // alloc error
You are returning the address of a variable with automatic storage. That object gets destroyed when the function returns. The solution is to allocate the object on the heap. I suggest using a smart pointer (unique_ptr or shared_ptr in combination with make_shared<>()) for that purpose and return the smart pointer.
std::shared_ptr<QgsSymbolV2> QGISFunc::ReadClassSymbolsXML(
QString FeatureType,
QXmlStreamReader &reader
)
{
try
{
...
std::shared_ptr<QgsSymbolV2> spObj = make_shared<QgsMarkerSymbolV2>();
...
return spObj;
}
...
}
Your problem has nothing to do with the class being abstract. You create an object on the stack and then return its address. That address though will no longer be valid after the function returns. If you really want to return a pointer and delegate ownership to the caller, why not create it on the heap with new? Don't forget to delete it though later when you are done with that object, or consider smart pointers as #AndyProwl suggests.
Related
I'm currently testing some simple AngelScript stuff, and noticed something I find a bit strange when it comes to how objects are initialized from classes.
Let's say I define a class like this:
class MyClass {
int i;
MyClass(int i) {
this.i = i;
}
}
I can create an object of this class by doing this:
MyClass obj = MyClass(5);
However it seems I can also create an object by doing this:
MyClass obj;
The problem here is that obj.i becomes a default value as it is undefined.
Additionally, adding a default constructor to my class and a print function call in each one reveals that when I do MyClass obj = MyClass(5); BOTH constructors are called, not just the one with the matching parameter. This seems risky to me, as it could initialize a lot of properties unnecessarily for this "ghost" instance.
I can avoid this double-initialization by using a handle, but this seems more like a work-around rather than a solution:
MyClass# obj = MyClass(5);
So my question sums up to:
Can I require a specific constructor to be called?
Can I prevent a default constructor from running?
What's the proper way to deal with required parameters when creating objects?
Mind that this is purely in the AngelScript script language, completely separate from the C++ code of the host application. The host is from 2010 and is not open-source, and my knowledge of their implementation is very limited, so if the issue lies there, I can't change it.
In order to declare class and send the value you choose to constructor try:
MyClass obj(5);
To prevent using default constructor create it and use:
.
MyClass()
{
abort("Trying to create uninitialized object of type that require init parameters");
}
or
{
exit(1);
}
or
{
assert(1>2,"Trying to create uninitialized object of type that require init parameters");
}
or
{
engine.Exit();
}
in case that any of those is working in you environment.
declaring the constructor as private seems not to work in AS, unlike other languages.
I am trying to manage the lifetime from an expensive object using manual memory management and during my unit-tests I seem to crash my program with an access violation in the main method underneath destroy(bar) in this example.
This is the minimal example for my problem where I get an access violation.
I don't understand what's going wrong.
class Foo { int i;}
struct Bar
{
Foo _p;
this(Foo foo)
{
_p = foo;
}
~this() {
import core.stdc.stdlib : free;
if (_p !is null)
{
destroy(_p);
free(cast(void*)_p);
_p = null;
}
}
}
void main(string[] argv)
{
import std.conv;
import core.stdc.stdlib;
Foo foo = emplace(cast(Foo) malloc(Foo.sizeof));
Bar bar = Bar(foo);
destroy(bar);
}
Note that destroy sets _p to null "for" you... which means you never actually free it. Do Foo tmp = _p; destroy(_p); free(cast(void*) tmp); instead, or something like that, so you keep a temporary copy of the reference beyond the destroy call. That's not what's causing your crash though, that is just a memory leak.
The crash is because, Foo.sizeof for a class is the size of the reference, not the size of the instance. For classes, you want to malloc(__traits(classInstanceSize, Foo)). The documentation mentions this as one of its preconditions: http://dpldocs.info/experimental-docs/std.conv.emplace.3.html
That's causing your crash because you didn't allocate enough space for the vtable (and thus emplace probably corrupted memory too, which eluded type checks due to your cast!). I would malloc and slice it instead of casting it.
// malloc the instance size then slice it to get a type-safe representation
void[] memory = malloc(__traits(classInstanceSize, Foo))[0 .. __traits(classInstanceSize, Foo)];
emplace!Foo(memory); // emplace a new one in that memory
You also should be careful when passing class references to that struct, since if it wasn't malloced or if there is another reference, you will get a dangling problem.
I found conception of Delegates pretty hard for me. I really do not understand why I can't simply pass one function to another and need to wrap it to Delegate. I read in docs that there is some cases when I do not know it's name and Delegate is only way to call it.
But now I have trouble in understanding conception of callbacks. I tried to find more information, but I can't understand is it's simply call of other function or what is it.
Could you show examples of D callbacks and explain where they can be helpful?
import vibe.d;
shared static this()
{
auto settings = new HTTPServerSettings;
settings.port = 8080;
listenHTTP(settings, &handleRequest);
}
void handleRequest(HTTPServerRequest req,
HTTPServerResponse res)
{
if (req.path == "/")
res.writeBody("Hello, World!", "text/plain");
}
&handleRequest is it callback? How it's work and at what moment it's start?
So within memory a function is just a pile of bytes. Like an array, you can take a pointer to it. This is a function pointer. It has a type of RETT function(ARGST) in D. Where RETT is the return type and ARGST are the argument types. Of course attributes can be applied like any function declaration.
Now delegates are a function pointer with a context pointer. A context pointer can be anything from a single integer (argument), call frame (function inside of another) or lastly a class/struct.
A delegate is very similar to a function pointer type at RETT delegate(ARGST). They are not interchangeable, but you can turn a function pointer into a delegate pointer pretty easily.
The concept of a callback is to say, hey I know you will know about X so when that happens please tell me about X by calling this function/delegate.
To answer your question about &handleRequest, yes it is a callback.
You can pass functions to other functions to later be called.
void test(){}
void receiver(void function() fn){
// call it like a normal function with 'fn()'
// or pass it around, save it, or ignore it
}
// main
receiver(&test); // 'test' will be available as 'fn' in 'receiver'
You need to prepend the function name as argument with & to clarify you want to pass a function pointer. If you don't do that, it will instead call that function due to UFCS (calling without braces). It is not a delegate yet.
The function that receives your callable may do whatever it wants with it. A common example is in your question, a web service callback. First you tell the framework what should be done in case a request is received (by defining actions in a function and making that function available for the framework), and in your example enter a loop with listenHTTP which calls your code when it receives a request. If you want to read more on this topic: https://en.wikipedia.org/wiki/Event_(computing)#Event_handler
Delegates are function pointers with context information attached. Say you want to add handlers that act on other elements available in the current context. Like a button that turns an indicator red. Example:
class BuildGui {
Indicator indicator;
Button button;
this(){
... init
button.clickHandler({ // curly braces: implicit delegate in this case
indicator.color = "red"; // notice access of BuildGui member
});
button.clickHandler(&otherClickHandler); // methods of instances can be delegates too
}
void otherClickHandler(){
writeln("other click handler");
}
}
In this imaginary Button class all click handlers are saved to a list and called when it is clicked.
There were several questions in the OP. I am going to try to answer the following two:
Q: Could you show examples of D callbacks and explain where they can be helpful?
A: They are commonly used in all languages that support delegates (C# for an example) as event handlers. - You give a delegate to be called whenever an event is triggered. Languages that do not support delegates use either classes, or callback functions for this purpose. Example how to use callbacks in C++ using the FLTK 2.0 library: http://www.fltk.org/doc-2.0/html/group__example2.html. Delegates are perfect for this as they can directly access the context. When you use callbacks for this purpose you have to pass along all the objects you want to modify in the callback... Check the mentioned FLTK link as an example - there we have to pass a pointer to the fltk::Window object to the window_callback function in order to manipulate it. (The reason why FLTK does this is that back FLTK was born C++ did not have lambdas, otherwise they would use them instead of callbacks)
Example D use: http://dlang.org/phobos/std_signals.html
Q: Why I can't simply pass one function to another and need to wrap it to Delegate?
A: You do not have to wrap to delegates - it depends what you want to accomplish... Sometimes passing callbacks will just work for you. You can't access context in which you may want to call the callback, but delegates can. You can, however pass the context along (and that is what some C/C++ libraries do).
I think what you are asking is explained in the D language reference
Quote 1:
A function pointer can point to a static nested function
Quote 2:
A delegate can be set to a non-static nested function
Take a look at the last example in that section and notice how a delegate can be a method:
struct Foo
{
int a = 7;
int bar() { return a; }
}
int foo(int delegate() dg)
{
return dg() + 1;
}
void test()
{
int x = 27;
int abc() { return x; }
Foo f;
int i;
i = foo(&abc); // i is set to 28
i = foo(&f.bar); // i is set to 8
}
There are already excellent answers. I just want to try to make simple summary.
Simply: delegate allows you to use methods as callbacks.
In C, you do the same by explicitly passing the object (many times named context) as void* and cast it to (hopefully) right type:
void callback(void *context, ...) {
/* Do operations with context, which is usually a struct */
doSomething((struct DATA*)context, ...);
doSomethingElse((struct DATA*)context, ...);
}
In C++, you do the same when wanting to use method as callback. You make a function taking the object pointer explicitly as void*, cast it to (hopefully) right type, and call method:
void callback(void* object, ...) {
((MyObject*)object)->method(...);
}
Delegate makes this all implicitly.
I have another odd problem with Objective C inheritance. I have a protocol called IGameObject, a class GameObject that inherits from NSObject and IGameObject and finally a Player that inherits from GameObject..
The problem is that when I assign a Player* to a IGameObject*, this produces an error, but it works ok when I assign a Player* to a GameObject*. I haven't seen that this is not possible in all I have read. Here the code:
-(IGameObject*) clone
{
Player* p=(Player*) 0xFFfFFFFF;
//Throws an error saying that Cannont initialise a variable of type IGameObject with an value of Player*
IGameObject* go=p;
//This works perfectly
GameObject* go2=p;
return [[Player alloc] initWithGameObject:self];
}
Could anybody guess what is happening?
Thanks in advance.
When returning (or declaring) a type that is only known by its interface, don't treat it as an object pointer. Instead, use:
-(id<IGameObject>) clone {
And:
id<IGameObject> go=p;
This should clear up that warning.
Sidenote: Why in the world are you assigning p to a memory address?!
You cannot create a pointer to a protocol
IGameObject* go=p;
is meaningless.
I need to do some maintenance on an Objective-C application (updating it to use a new API), and having never used the language before, I'm a bit confused.
I have an Objective-C++ class which implements an interface from my API, and this is used within a block, however whenever it is accessed within the block, it fails with an access violation error (EXC_BAD_ACCESS).
Furthrer investigation shows that none of the constructors for the object in question are being called. It is declared within the containing scope, and uses the __block modifier.
To try and understand this, I made a quick scratch application, and found the same thing happens there:
class Foo
{
public:
Foo() : value(1) { printf("constructor"); }
void addOne() { ++value; printf("value is %d", value); }
private:
int value;
};
void Bar()
{
Foo foo1; // prints "constructor"
__block Foo foo2; // doesn't print anything
foo1.addOne(); //prints "2"
foo2.addOne(); //prints "1"
}
Can anyone explain what is happening here? Why isn't my default constructor being called, and how can I access the object if it hasn't been properly constructed?
As I understand it, your example there isn't using a block as such, but is declaring foo2 as to be used by a block.
This does funny things to the handling of foo2, which you can read more about here.
Hope that helps.
Stumbled upon this old question. This was a bug that's long been fixed. Now __block C++ objects are properly constructed. If referenced in a block and the block is copied, the heap copy is move-constructed from the original, or copy-constructed if it cannot be move-constructed.