As we all know, Q_OBJECTs are instances and are not copyable.
Is there any kind of syntactic sugar to copy all static and dynamic properties of an arbitrary QObject derived class?
It seems such a nobrainer, but I can't find any reference to such - obviously implementing one myself should be quite trivial - loop over metaObject(), loop over dynamicPropertyNames(), set accordingly.
You could implement a copy helper class as follows.
/** Enable QObjects to be explicitly copyable by copying property values. */
template<class T>
class QObjectCopyHelper<T>
{
protected:
explicit QObjectCopyHelper(T *client) : m_client(client) {}
public:
T *clone(QObject *parent = 0) {
T *copy = new T(parent);
// loop over and copy properties from m_client to copy
// (both from T::staticMetaObject and dynamic ones)
return copy;
}
private:
T *m_client; // <-- I think we need this, but I might be wrong
};
Then you can use this in any QObject subclass with very low work needed to be done:
class MyClass : public QObject, public QObjectCopyHelper<MyClass>
{
Q_OBJECT
...
};
However, this still needs clone() to be called (the ugly "Java-style"). So we can additionally define a copy constructor just calling clone() and you also might think of a assign() method called within the assignment operator.
Please note that this really copies the properties only! There are a lot of other things being tracked in QObject, like the current connections. They explicitly forbid copying QObjects because it would be very difficult to define rules on how this should be done, and these rules would be the correct ones for some use cases only, while in others you want other rules...
A solution is discussed here, where they take the loop-over-the-properties approach. There seems to be no "syntactic sugar" here.
Related
I am new to Qt and I want to try to understand it better.
I know from an inheritance perspective that a QMainWindow is derived from QObject. (Directly/Indirectly)
This allows for us to connect signals to slots in the following ways within the QMainWindow:
`
1- QObject::connect(sender, &QObject::signal, this, &MyObject::slot);
2- connect(sender, &QObject::signal, this, &MyObject::slot);
`
Even tough both ways are a possibility, I never understood what the major differences between them are.
Here are my questions:
1- Which method is more performant and why?
2- Why do programmers sometimes use one over the other?
I used both of these methods and they both seem to work similarly.
Consider following code.
class Foo {
static void fn();
};
class Bar: public Foo {
void bar() {
// 1
}
};
void main() {
// 2
}
If you want to call Foo::fn() at 1, you can just write fn(); since static functions is "visible" inside methods in derived classes, you can also write Foo::fn() and it will do exactly the same. If you want to call it at 2, you can only use full name Foo::fn().
We are in the process of converting C# code to C++, but we need to do so in phases. I am at a point now where I need to instantiate several native objects from within managed code. These native objects I cannot change, and their declaration looks like this:
public class NativeA();
public class NativeB(std::shared_ptr<NativeA> obj);
Both NativeA and NativeB need to be instantiated from managed code as:
void main() {
ManagedA ObjectA = gcnew ManagedA();
ManagedB ObjectB = gcnew ManagedB(ObjectA);
}
The problem comes in with getting the shared_ptr of NativeA in the constructor of NativeB. Niether NativeA nor NativeB will be manipulated in managed code, they just need to be instantiated. Ideally, something like this:
public ref class ManagedA {
public:
ManagedA() { _object = new NativeA(); }
~ManagedA() { delete _object; }
NativeA * Get() { return _object; }
private:
NativeA *_object;
};
public ref class ManagedB {
public:
ManagedB(ManagedA^ objectA ) {
_object = new NativeB(std::make_shared<NativeA>(*objectA->Get());
}
~ManagedB() { delete _object; }
private:
NativeB *_object;
};
But, this is not allowed in c++/cli because native types are declared as private. Defining #pragma make_public(NativeA) does not solve this either.
My intent is not to work with the native objects in managed code, they just need to be instantiated, so I really don't care about trying to marshal the native pointers and deal with .NET GC if I don't have to, and I don't want to perform a copy. I just want to wrap the classes in order to pass them around.
Is there a clean and simple way to do this?
It appears that the answer was not due to a syntax or usage problem. The two managed objects were in different DLLs and could not be passed across them via .NET. Once the code was compiled in the same project, the issue was resolved.
Although the error message indicated the problem was an accessibility issue in VS 2015, and because it reported it during the link phase, I suspect the cause was because the linker would not have known about the implementation of the NativeA in NativeB without declaring an extern. Being wrapped in CLR, it surfaced as a different issue.
This question already has answers here:
How do I call ::std::make_shared on a class with only protected or private constructors?
(19 answers)
Closed 7 years ago.
I am currently following the book **Effective Modern C++" and it says
Avoid creating std::shared_ptrs from variables of raw pointer type.
And I am convinced with the explanation so that I, too, agree on that we need to avoid. But there is an exception I encountered.
class Person
{
protected:
Person();
public:
static std::shared_ptr<Person> getShared()
{
return std::shared_ptr<Person>(new Person());
}
When we hide the default constructor std::make_shared cannot do its job. That's why I use a static method in the example above. My question is
Is this best I can do about the situation?
I still use raw pointer to create a shared_ptr, but in this case I can predict what may happen to this pointer. Does this practice still threaten my code?
Although this might not be the best way to do that, one way to do get your constructor protected to a certain degree but still make it callable by std::make_shared is the following:
class MyClass
{
protected:
struct ConstructorGuard {};
public:
MyClass(ConstructorGuard g) {}
static std::shared_ptr<MyClass> create()
{
return std::make_shared<MyClass>(ConstructorGuard());
}
};
The constructor itself is public, but it cannot be called from outside the class, because it requires an argument of type ConstructorGuard which is a protected nested class, such that only the class itself (and the derived classes) can construct such an object to pass it to the constructor.
I use observer-observable pattern in my program. Everything worked before I had to change the code a little. If to be exact I changed the inheritance of IObserver class - right now it inherits QObject:
class IObserver : public QObject
{
...
I did it because of only one thing - I need deleteLater() method to be used in an observer, so I would be able to call implementation of virtual function deinitialization() of IObserver. Thus I could standardize every IObserver message handler.
The problem is, I already inherited QObject (indirectly) in some Observer classes. Like MainForm or AboutDialog. Everything is going fine until I try to call "connect" method in AboutDialog class.
What can I do? I really need this deleteLater() method since I can't use "delete this" in IObserver code - this will call IObserver destructor, not the MainForm or Storage classes for instance.
Thank you.
I really need this deleteLater() method since I can't use "delete this" in IObserver code - this will call IObserver destructor, not the MainForm or Storage classes for instance.
If you make your destructor virtual (and you should!) it will call the derived destructor just fine. But a problem is that destructing a object while it is handling some signal/slot might cause problems with the event loop. You would have to be very careful with delete this anyway.
The problem is, I already inherited QObject (indirectly) in some Observer classes.
One way you could implement this, not sure if the best thought:
template <typename Derived>
class IObserver
{
// Just to be sure: (C++11)
static_assert(is_base_of<Derived, QObject>::value,
"must inherit from QObject when using IObserver");
void deleteMe()
{
QObject* thisObject = dynamic_cast<QObject*>(this);
// no need for check if thisObject equals null. static assert does this.
thisObject->deleteLater();
}
};
class MainForm : public IObserver<MainForm>, public QMainWindow
{
// ...
};
I believe this pattern is called static polymorphism.
Abandon inheritance of QObject for IObserver. Instead of that add such method to interface.
class IObserver : public QObject {
public:
QObject *object() const = 0;
...
Then if implementation of interface inherits the QObject you will return this pointer from object() method. If implementation of interface doesn't inherit QObject you can simply return pointer to some simple QObject which will handle destruction of this object.
Then you can simply connect deleteLater for object returned by this method.
Off topic
Use of interfaces for observing in Qt usually is obsolete, slots and signals do this job perfectly and this is more flexible approach.
I have derived QGraphicsItem and QGraphicsScene classes. I want the items to be able to call scene() and get a derviedGraphicsItem * instead of a QGraphicsItem *, so I reimplemented QGraphicsScene::itemAt to return a derived pointer.
DerivedItem* DerivedScene::itemAt( const QPointF &position, const QTransform &dt ) const
{
return qobject_cast< DerivedItem * >(
QGraphicsScene::itemAt(position, dt) );
}
I get the following error (Qt 4.6, GCC 4.4.3 on Ubuntut 10.4)
scene.cpp: In member function ‘DerivedItem* DerivedScene::itemAt(qreal, qreal, const QTransform&) const’:
scene.cpp:28: error: no matching function for call to ‘qobject_cast(QGraphicsItem*)’
I then noticed QGraphicsItem doesn't inherit QObject, so I made my derived QGraphicsItem class have multiple inheritance from QObject and QGraphicsItem, and after adding the Q_OBJECT macro and rebuilding the project I get the same error.
Am I going about this the wrong way? I know it's supposed to be bad design to try to cast a parent class as a child, but in this case it seems like what I want, since my derived item class has new functionality and its objects need a way to call that new functionality on items around themselves, and asking the items scene object with itemAt() seems like the best way - but I need itemAt() to return a pointer of the right type. I can get around this by having the derived items cast the QGraphicsItem * returned by QGraphicsScene::itemAt() using dynamic_cast, but I don't really understand why that works and not qobject_cast, or the benefits or disadvantages to using dynamic_cast vs. qobject_cast.
EDIT:
forgot to mention that I also reimplemented QGraphicsItem::scene() in my derived class to return a DerivedScene *, as
DerivedScene* DerivedItem::scene() const
{
return qobject_cast< DerivedScene * >( QGraphicsItem::scene() );
}
but this doesn't appear to be causing a compilation error...
There is no point in inheriting from QObject just for casting. The advantage of qobject_cast
over dynamic cast is summed up pretty much in the qobject_cast documentation:
The qobject_cast() function behaves similarly to the standard C++ dynamic_cast(), with the advantages that it doesn't require RTTI support and it works across dynamic library boundaries.
It's nice to have and useful if you have QObjects, but not worth to inherit from QObject if it is all you want from QObject.
Also, for QGraphicsIems there is qgraphicsitem_cast, which should do exactly what you want :)
You have to pass a QObject pointer to qobject_cast() and QGraphicsScene::itemAt returns a QGraphicsItem pointer. Since, as you mentioned, QGraphicsItem does not derive from QObject, the complier gave you that error.