Adapting C++ execution order to Xojo

As I stated earlier, my current project partly depends on porting c++ code’s logic. That code’s methods constantly calls “this->{SomeMethod}” from inside a superclass’s instance of a method and then relies on variables having already been set up by the superclass(es) in the leaf class’s code, even in Constructors. For example, the superclass method invoke_build calls this->build in the middle of its execution, where each leaf class has its own implementation of build.

As Xojo’s inheritance logic is “replace” rather than “extend”, how can I adapt this logic without either A) putting all the code in each leaf class or B) winding up in an infinite loop as a result of a single mistake while calling “Super”?

Sorry for all these relatively basic questions, but I studied c/c++ at University over 15 years ago, so the rust has rust on it!

You should post the code.

It will be a lot easier to see what you are talking about.

“this” in Xojo is “Me”. If it calls itself, it is a classic recursion scheme.

Here’s the actual code from “invoke_build”

void invoke_build(Document *document, XMLNode repr, unsigned int cloned)
{
/
Bookkeeping */

this->document = document;
this->repr = repr;
this->cloned = cloned;

/* Invoke derived methods, if any */
this->build(document, repr);

if ( !cloned ) {

As a realistic example of the situation I’m (trying to) deal with say both invoke_build and build exist in “MyObject”, “MyItem” {SUPER MyObject] has an implementation of build as well, and “myLeaf” [SUPER MyItem] again has an implementation of build. MyLeaf’s build expects both MyObject’s and MyItem’s build’s to have been invoked in that order before its own build is invoked!

You can call Super.build to invoke the superclass’ method.

myLeaf.build implementation:
super.build
//myLeafCode

myItem.build Implenentation:
super.build
//myItemCode

myObject.build implementation:
//myObjectCode

Do I need a “Completed” Property to avoid having other objects descended from “MyObject” or “MyItem” calling Super.build needlessly? It looks like a would.

this->build(document, repr);

I think if you call a method of subclass, you’d better go in Xojo with implementing an event method.
This can be implemented in subclasses and optionally forwarded to sub subclass.

This depends on the code of the subclasses‘ Build method. Hard to say without knowing the classes more in depth.

This is not completely true. An extension approach in Xojo could use an event scheme: The build method of the superclass raises a SetupBuild event first which the subclasses‘ handlers use to set up the parameters, then the superclass‘ real Build code runs. Or similar, according to your needs.

Edit: Christian was faster.

Antonio illustrated the way I would approach it. If the first line of every child class build method is “super.build” then you will get the execution order you desire. MyObject.build will complete first, then MyItem.build, then MyLeaf.build.

In this example if you need a Completed property then something is wrong and your code is needlessly open to a stack overflow condition due to endless recursion.

I’m guessing from the snippet of code you posted, but it looks like they organized the logic as MyObject.invoke_someMethod and MyObject.someMethod to deal with the fact that there’s no generic “super” keyword in C++. From a child class you have to refer to the parent explicitly when calling its method due to multiple inheritance. So they probably gathered all the common code to invoke_someMethod and left the class specific code in someMethod. (Forgive me if I’m wrong. Again, I’m going off the snippet that was posted.)

Personally I think that’s a poor approach even in C++. In a language with “super” it makes no sense at all. Again, you can get the execution order you want. So code common to a group of child classes should just go in the parent method of the same name. In this case the bookkeeping code would just exist in MyObject.build and there would be no invoke_build.

Now Xojo events explicitly propagate from parent to child, no first line call to super required. But they also effectively forbid a child from overriding the parent’s behavior. A child cannot even extend that behavior unless the parent exposes it by raising the event. In general you do want a child class to be able to extend or override a parent method, even just to cover future changes. So I stick to methods except when and where I clearly need events.

@Daniel Taylor Thank you very much! I had completely forgotten about c++'s multiple inheritance “feature” and its cousin, the “friend” keyword! Therefore, I wasn’t seeing that “invoke_” was just a “Super” lack workaround.

Speaking of “friend”, when two classes declare each other as friends in c++, is the best workaround to introduce a common super class and move their friendly properties there with “Protected” access or am I missing something again?

That depends on the code in question and what you wish to accomplish. There are certainly valid uses of friend where you would not want to refactor the code into a common super class. But where there is a strong “friendship” between two or more classes it’s worth considering.

You can also implement friend-like behavior using interfaces. Make an interface containing the methods that friends can access, apply it to the receiver and then make the receiver’s methods private. Only the receiver and the objects which refer to the class using the interface can access those methods.

I don’t know C** but I have used this pattern in Xojo/RB.

One more step could be to to put all of them in the same module and make the friend classes at least private so that they can not be used and should not autocomplete outside of the module. The same can be done with the interface itself itself if it is not needed outside the module.

Helps organize the friend classes and not pollute the global name space and keep autocomplete lists smaller.

  • Karen