From Java to C++

Started by
6 comments, last by Antheus 14 years, 2 months ago
I'm having trouble applying some of the concepts I use at my day job coding in Java to my hobby project using C++. Let's just say Java has me somewhat spoiled with its instanceof operator and using reflection to treat class definitions as just another variable. (I'm referring to the Class<?> object here) On the java side, we are all about separation of responsibilities. When we have a class hierarchy of objects, and sets of operations to be performed using those objects, we're very hesitant to just say ok, Object X knows how to perform operation Y on itself. We'll create a factory that produces objects that know how to perform the operation on the given Object. The rationale for this is that when operations needs to change, or be outright replaced, there is one central place to do that, and we don't have operation logic spread out through our Object hierarchy, nor do we risk having to change Object's interface and break a bunch of other code using it. The piece I'm trying to fill in in C++ is how does the factory decide which type of operation to return based on an object given? In java, you can just create a map of Class<? extends MyObjectInterface> to Class<? extends OperationInterface>, and look up the type of and produce operation instances using reflection. One solution I've seen for C++ is dynamic_cast to try to guess what type of object is passed in, but that seems kind of sloppy, and too much of trying to cram a java shaped peg into a C++ shaped hole. Another alternative is to have a virtual getType() method in your Object hierarchy and the factory can use that. I think I'm leaning towards the getType() method so the Objects don't know how to perform an operation on themselves, but they do know how to instruct factories to create operation performers. Do either of these sound acceptable, or is there a whole other design paradigm or philosophy I should be applying in C++?
Advertisement
I think you'll probably want to look-up the visitor pattern. It's applicable in Java and C++ and does not require reflection, dynamic_casts or any kind of RTTI.

But if you gave more details, someone might be able to provide a more C++-centric approach to your specific problem.
I haven't completely understood what you are trying to do but I would consider both bad designs in C++. It looks like you are over-complicating everything to just being generic.
I guess I didn't really have a specific case in mind when I posed the question, I was more wondering if there was something similar to Java's class mapping driven factories in C++. I'm gathering that the answer is that its much easier to generalize something like that in Java, and while possible, not really a good idea in C++. Here is a more specific case:

Say I have a class hierarchy of pieces of data. They all have some attributes in common, so those are contained in a common base class. I put those objects into a container, referring to them by the base class. Now say I select an object from the container, again only referring to it by its base class type, and I want to build a dialog to edit that object. A possible Java way would to have a factory that maps concrete data classes to editor dialog classes, and use reflection to return an instance of the editor dialog. Is there a C++ way to do this, or is my design flawed already?

EDIT:

One solution might be to build the logic into the data classes so that each one knows how to produce a dialog capable of editing itself, and I could very well do that, but as the system grows and there are more such operations added, the data object classes could get pretty overloaded.
Quote:Original post by Matt328

The rationale for this is that when operations needs to change, or be outright replaced, there is one central place to do that, and we don't have operation logic spread out through our Object hierarchy, nor do we risk having to change Object's interface and break a bunch of other code using it.


No, the rational is that your object model is broken, improperly designed, and needs to use layer upon layer of crud to reinvent polymorphism several times in a row.

Quote:Do either of these sound acceptable, or is there a whole other design paradigm or philosophy I should be applying in C++?


My personal philosophy is "GoF patterns and design paradigms are shit, solve the problem instead."

The Java version of original problem:
public interface Operation {  void execute();}public interface OperationProvider {  Operation makeOperation();}... void runOperation(OperationProvider p) {  Operation op = p.makeOperation();  op.execute();}
The translation to C++ is straight-forward, the rest are implementation details.

A factory takes a key, and returns an instance. This is why it is necessary to first determine what the key is. Then, define factory interface:
public interface PrintFactory {  Operation makePrintOperation(Document d);}


Implemented in previous design, it looks something like this:
public class PrintDocumentProvider implements OperationProvider {  Operation makeOperation() {    return printFactory.makePrintOperation(d);  }  private PrintFactory printFactory;  private Document d;}


And this is where the "separation of responsibilities" happens. OperationProvider provides Operations. And operations know how to execute themselves (aka Command pattern).

How these operations come to be is a matter of specific implementation. In case of DI, PrintFactory would be provided in constructor, made by IOC container factory.


The above translates literally to C++, or any other similar language, is completely decoupled via interfaces, and can be managed centrallyvia IOC type factories. There is no need for instanceof, dynamic_casts, or anything similar.


Anytime you are given an object, and you need to guess the type in one way or another, rather than using virtual function/method call, it is a design flaw, and everything else is just trying to cover for that.

Quote:A possible Java way would to have a factory that maps concrete data classes to editor dialog classes, and use reflection to return an instance of the editor dialog. Is there a C++ way to do this, or is my design flawed already?

That isn't Java way.

Java and OO way is to have a base class, something like:
public BaseClass {  abstract Dialog makeUIDialog();}
Then, each variation of BaseClass implements makeUIDialog directly, or as is the case with previous Print example, it contains a reference to a factory, which makes a specific dialog based on some concrete parameters.



If you need to use reflection of data members to build contents of the dialog, then this is a matter of an interface again. Something like:
public interface DialogFactory {  Dialog build(Reflectable b);  // use reflection to walk the b, and add appropriate UI elements};
Since C++ doesn't have built-in reflection capabilities, the above would need to be provided manually using a visitor. For each Reflectable, there would be a virtual visit() or walk() or build() method, which you would implement yourself, for each data member.

Again - none of this, in any way, requires automatic reflection or guessing of data types, the concepts are exactly the same in Java or C++.
Quote:public BaseClass {
abstract Dialog makeUIDialog();
}

Then, each variation of BaseClass implements makeUIDialog directly, or as is the case with previous Print example, it contains a reference to a factory, which makes a specific dialog based on some concrete parameters.


Thanks!! I had just gotten done googling DI and IOC and was still scratching my head a bit, but that right there switched the light on for me.
Quote:Original post by Antheus
Since C++ doesn't have built-in reflection capabilities

C++ has the typeid operator. Couldn't you just map from type_info to something else?
Quote:Original post by DevFred
C++ has the typeid operator. Couldn't you just map from type_info to something else?


There are very few cases where using typeid/instanceof approach is needed. Polymorphic call already *is* a map.

Simple case, class is the implicit key:
class Foo implements/extends SomeBase  {  public Baz makeBaz() {  // virtual    return ...  }}


Extended case, instance is the key:
class Foo implements/extends SomeBase {  Foo(BazFactory f);  public Baz makeBaz() {  // virtual    return f.make(...);  }  private BazFactory f;}


In either case, if something can make a Baz, then it should be inherit from SomeBase which expresses this.

The above obviously doesn't cover non-technical consequences of flawed abstractions, misapplication of patterns, or improper domain model. In enterprise setting, all of such flaws are much more likely to persist due to general aversion or inability to take responsibility beyond whatever individual task is assigned to someone.

The above cannot represent multimap factories, but just needing those screams like a massive overcomplication of the design. And then there is still the cheap way out, refactor the common interface to be a multi-factory which can return arbitrary number of distinct types.

Obviously, once OO hierarchy is elaborate enough, it will become rigid, and as requirements change, it will often define incorrect abstractions or become unwieldy. DI/IOC cannot solve this, but it makes refactoring in response considerably cheaper, since actual logic is tucked away in standalone classes or free functions, and just bindings change.

Conversely, less reliance on inheritance based designs, preferably with languages which make it painless to so avoids some of these problems altogether (Python, Ruby, &#106avascript), but introduces a whole different set of potential issues.

This topic is closed to new replies.

Advertisement