How to emit signal through a few class objects in Qt? - c++

I have a few classes: Class A - highest class, Class B and Class C which are initialized in Class A constructor. In Class B constructor is initialized Class B1 and in Class C constructor is initialized Class C1. C1 object and B1 object does not see each other.
Every time I need to send signal from C1 class to B1 class, I connecting C1 and C, C and B, finally, B and B1. So every time my programm emitting a signal in C1 class object, it is sending to C class object then to B and then to B1. (On image) Is it a right Qt Way? Or there is a better way to do that?

You could add to class C an interface which returns C1 and a similar interface to class B, too. Then after creating classes C and B, class A could ask C1 and B1 and connect C1's signal to B1's slot.
Or, if you have lots of these kind of cases and you definitely don't want to expose classes C1 and B1 to A, you could create your own signaling mechanism. Some kind of "post office" where classes could register as receivers and to where classes could send messages. In this case, class B1 would register as a receiver and class C1 would send messages. C1 and B1 would know nothing about each other. The post office class would send C1's message to B1. This kind of "post office" class could also be implemented using Qt's signals and slots.

Related

Preventing descendants from overriding method

In C++ (11/14/17, I don't care), I have a base class B which exposes method x as protected.
In class D1, which derives from B, I want to prevent further descendants (of D1) from calling x(). Now, if I were overriding x in D1, I would simply mark it as final.
But, what if D1 does not override x(), yet D1 still wants to hide it from descendants? How can I do that?
How can I do that?
By changing the program and overriding x in D1. You can just delegate to the base class version by calling it.

Accessing signal of privately inherited ancestor

I have created class B (a descendant of QObject), whose public & protected methods should be visible to descendants of B but not to any classes outside of those descendants. So descendant class D inherits from B as private:
class B : public QObject {}
class D: private B {}
However, in D I need to connect to signals emitted from B. The only way I can connect to those signals is to inherit B as public. Otherwise I get a compiler error that
QObject is an inaccessible base of D
Does that mean D must inherit from B as public, and I must create private methods in D to override every public method in B? and somehow hide enums, etc. (Seems like a lot of work, there must be a better way)
I am using Qt 5, and I thought in Qt 5 onwards signals are public. Or is the connect method hidden? Note that B contains some virtual methods that need to be overridden by D, so I cannot just make B an member of D.

ladder-like C++ virtual inheritance

If I have a class inheritance relation like the following
a
/ \
b c
\ |
| d
\/ \
e f
\ /
g
Is the following the correct definition?
class A {};
class B: public virtual A {};
class C: public virtual A {};
class D: public C {};
class E: public B, public virtual D {};
class F: public virtual D {};
class G: public E, public F {};
I made both A and D virtually inherited because I assume each joint class need to be virtual.
Also I am not sure how C++ defines the constructor order of the above case. The link
https://isocpp.org/wiki/faq/multiple-inheritance#mi-vi-ctor-order says
The very first constructors to be executed are the virtual base
classes anywhere in the hierarchy. They are executed in the order they
appear in a depth-first left-to-right traversal of the graph of base
classes, where left to right refer to the order of appearance of base
class names.
After all virtual base class constructors are finished, the
construction order is generally from base class to derived class. The
details are easiest to understand if you imagine that the very first
thing the compiler does in the derived class’s ctor is to make a
hidden call to the ctors of its non-virtual base classes (hint: that’s
the way many compilers actually do it). So if class D inherits
multiply from B1 and B2, the constructor for B1 executes first, then
the constructor for B2, then the constructor for D. This rule is
applied recursively; for example, if B1 inherits from B1a and B1b, and
B2 inherits from B2a and B2b, then the final order is B1a, B1b, B1,
B2a, B2b, B2, D.
Note that the order B1 and then B2 (or B1a then B1b) is determined by
the order that the base classes appear in the declaration of the
class, not in the order that the initializer appears in the derived
class’s initialization list.
If so, is the order like?
A, D, B, C, D, F, G
I do not expect D is constructed before C. What is the correct constructor order?
When constructing an object of class G, the virtual base classes are initialized first. This results in the constructors for A and D being called. The constructor for D will construct it's base C object. Then the constructors for the non-base classes of G will be called, which would be E and F. The constructor for E will call the constructor for B. This gives the final order:
A C D B E F G
I added constructors that call printf to watch what happens (code available on Godbolt for the curious). The order I got, with both clang (version 6.0.0) and gcc (versions 6.4.0 and 7.3.0), is:
A
C
D
B
E
F
G
This matches what I'd expect. A and D have to be constructed first, but you can't construct a D without a C (imagine a more complex example where D's constructor called into C. Once all virtual inheritance has been satisfied, the constructors are called in the same order we expect.

How does class casting work?

Consider c1 is the base class of c3. The below code works perfectly.
c1 obj1=new c3();
c3 obj2=(c3)obj1;
But, There is a ClassCastException in the below one
c1 obj1=new c1();
c3 obj3=(c3)obj1;
What have I missed?
I think what's happening is that you are creating obj1 as an instance of c1, and then trying to cast it to class further down the inheritance chain than c1.
In your first example, c1 is a base type of c3 and so you can create an instance of c3 where the type is c1..that's fine. c3 is a child of c1 and so inherits all its properties and methods.
In the 2nd example, however, you are creating an instance of c1 with a type of c1. You are then trying to cast it to its child. A child class may have additional properties and methods that the parent doesn't have.
To summarise, a child can be of its parent type and cast to it, however, a parent cannot be its child and cannot be cast as such.
If you need further clarification, let me know.

When using a virtual base class in a multiple inheritance scenario, is it necessary for all derived classes to reference the virtual base?

The US Air Force's JSF C++ coding standard requires that the virtual base class be declared for each derived class that accesses the virtual base.
For example, in the following hierarchy:
A
/ \
B1 B2
C1 C2
\ /
D
... the rule they impose in this standard (AV Rule 88.1, for reference), requires the classes to be declared like so:
class A;
class B1 : virtual A;
class B2 : virtual A;
class C1 : B1, virtual A;
class C2 : B2, virtual A;
class D : C1, C2, virtual A;
My questions are as follows:
Is this semantically different from only inheriting virtually in the declaration # B1/B2, and not specifying virtual A at each subsequent class declaration?
If it's semantically different, why would anyone /want/ to leave it off? It seems silly to me that you'd absolutely have to do this at each layer of inheritance since that adds a potential point of failure.
It semantically identical, since each derived class will have exactly one virtual base of type A. Mentio­ning the virtual base explicitly is quite nice, because the most-derived class constructs the virtual base (unlike what happens for non-virtual bases), and the construction order is important to keep in mind when writing the constructors of the derived classes.
I don't have a technical answer for (2). You don't have to do it, but it would be nice if you did. Like calling your parents, I suppose. As with many things, C++ doesn't force you to be reasonable.