PDA

View Full Version : protected QGraphicsObject



stefan
19th August 2011, 03:32
Hi!

I want to create class that inherits QGraphicsObject but dont want public QGraphicsObject function to be accessible from my class.

I can do the following:

class MyObject : protected QGraphicsObject
But then I cant add object to a scene

_scene->addItem(my_object);

Any advice?

Thanks

Santosh Reddy
19th August 2011, 04:09
It will not be directly possible to do so, as you have protected inheritance. The very point of having protected inheritance is to hide public functions, without exposing the public function of QGraphicsObject you will not be to use it / add it to any scene.

Well there is a work around :)


class MyObject : protected QGraphicsObject{};

MyObject my_object;

QGraphicsObject* gra_object= reinterpret_cast<QGraphicsObject*>(&my_object); // C++ style, static & dynamic cast will not work, as they obey strict type and visibility rules. dynamic cast overrides them
//QGraphicsObject* gra_object= (QGraphicsObject*)(&my_object); // C Style, not recommended, but works

_scene->addItem(gra_object);

stefan
19th August 2011, 04:48
Thanks for your answer! But I think I found more elegant solution...
How about this?

QGraphicsObject* MyObject::getBaseGraphicsObject(void)
{
return this;
}
and then:


_scene->addItem(my_object->getBaseGraphicsObject());

It is working, but im not sure if I could have other problems because of this?

Santosh Reddy
19th August 2011, 05:10
_scene->addItem(my_object->getBaseGraphicsObject());
This one looks nice, and avoids odd looking cast operator :). I don't think this will cause any other problems related to graphics scene/view, it should be good as long as the handle to QGraphicsObject* is available to scene.

wysota
19th August 2011, 08:51
Aren't you exposing the graphics object interface to the public this way?

Santosh Reddy
19th August 2011, 16:40
wysota is right, this way graphics object interface is exposed as public, then making QGraphicsScene as a friend of MyObject should help.

wysota
19th August 2011, 17:04
I think a better approach would be to hide the implementation completely and only expose the interface of MyObject to the world, like so:


class MyObject {
public:
virtual void method1() = 0;
virtual void method2() = 0;
};

class MyObjectImpl : public QGraphicsObject, public MyObject {
public:
MyObjectImpl(QGraphicsItem *parent = 0) : QGraphicsObject(parent) {}
void method1() { ... }
void method2() { ... }
};

class MyObjectFactory {
public:
MyObject *createMyObject() { return new MyObjectImpl(...); }
};
You can declare the MyObjectImpl class in .cpp file to hide it completely from the developer and only expose MyObject interface. Of course if you don't allow outside world to create MyObject object, you don't need MyObjectFactory at all and can just instantiate implementation objects directly.

An exercise to the reader: which two design patterns does this approach make use of?

Added after 4 minutes:

There is also this possibility:


class MyObject {
public:
MyObject() { impl = new MyObjectImpl(this); }
void method1() { impl->method1(); }
void method2() { impl->method2(); }
private:
MyObjectImpl *impl;
};

class MyObjectImpl : public QGraphicsObject {
public:
MyObjectImpl(MyObject *o), QGraphicsObject(), iface(o){}
void method1() { ... }
void method2() { ... }
private:
MyObject *iface;
};

Again, what design pattern is that? I can give a hint that it makes more sense to use it if you want to subclass MyObject one day.