4

Short version:
Consider the following pseudo-code:

class Foo {
    private:
        abstract type myVar;
} // This class is abstract

How would you implement this behaviour in standard C++?


Long version:
I have to port a lot of Obj-Oriented code from Matlab to C++. Note that I am the least experienced person in the world with Matlab and I do not use C++ since 2007.

I googled a lot on this topic but i couldn't find a proper answer to my question. So here I am :)

Let's say that you have this matlab class:

classdef Foo < handle
    properties (Abstract, Dependent)
        A
    end

    properties
        B
    end

    methods (Abstract)
        computeA()
    end

    methods (Access = protected)
        function obj = Foo(bar)
            obj.B = Matlab.BlaBlaBla(bar)
    end
end

This class (i suppose) cannot be allocated "directly" since it's constructor is protected. Also is property "A" is Abstract (ignore for a moment the fact that is also Dependent). MathWorks tells us that this means that:

  • Concrete subclasses must redefine abstract properties without the Abstract attribute, and must use the same values for the SetAccess and GetAccess attributes as those used in the abstract superclass.
  • Abstract properties cannot define set or get access methods (see Property Access Methods) and cannot specify initial values. The subclass that defines the concrete property can create set or get access methods and specify initial values.

So how would you correctly translate such behaviour in C++? Would it be right if I do as follow? (By right I mean that it is not a bad design practice)

class Foo {
    private:
         type A;
         type B;
    protected:
         virtual void computeA() = 0;
         Foo(type bar) { this.B = SomeFoo(bar); }
}

What I think (and I may be wrong) is that if I'm doing so one will have to do

class Subclass: Foo {
    protected:
        void computeA(){...} 
    public:
        type A() { computeA(); return A; } //This is A getter that grants Dependent behavior
}

Or otherwise get an error at compile time.

Am i wrong? Is there a better way to do so? Also is the that right way to translate the Dependent keyword?

Alessandro L.
  • 398
  • 1
  • 15
  • 2
    At least based on your description, it sounds to me like Matlab properties are enough of a mess (read that as "foreign enough to C++", if you prefer) that *any* translation into C++ is going to do one of two things: either change the code a lot, or end up as fairly poor (or at least strange) C++. – Jerry Coffin Jan 16 '13 at 14:11
  • 1
    The Abstract keyword definition has been taken from MathWorks website. Also I don't think that a behavior such the one obtained by using the Dependent keyword is such strange in C++. It grants you that the attribute A gets computed only if you need it and it grants you that it is always updated when you use it. Also put into account that i might have misunderstood what Dependent means for matlab :) – Alessandro L. Jan 16 '13 at 14:23
  • note that Subclass cannot access Foo's private member A. – Philipp Jan 16 '13 at 15:11
  • 1
    Let me give one example of what I mean. C++ makes it easy to compute a value when needed -- no problem there. Declaring in a base class that this will happen in all derived classes -- well, sorry, but I don't know of a way to do that. That said, I see no reason to do so -- in C++, telling a user that the value they will be up to date is roughly equivalent to telling somebody that the water you're giving them will be wet. Unless you specify otherwise, everybody's going to assume that's the case. – Jerry Coffin Jan 16 '13 at 15:13
  • 1
    Ok so Dependent is a simply replicable behavior. What about the Abstract? – Alessandro L. Jan 16 '13 at 16:18

1 Answers1

2

First of all, I think it is important to ask: what's the public interface of a class (what are its responsibilities, how does it interact with others)?

From your Matlab code, the answer is: the class defines to properties A and B as well as the method computeA. From my understanding of Dependent properties, I doubt that computeA() should be public (see the Matlab docs). If the rest of your code needs this, of course you can leave it public, but I'd try to reduce the accessibility.

Now the concept of a Property does not exist in C++. The funny thing about Matlab is that the base class decides whether there is A.get, A.set or both as well as the accessibility. I don't know the rationale behind that, but it doesn't seem to make too much sense in my eyes. In C++, I would translate properties to get/set methods. See this question for a discussion of implementing these in C++. Depending on your choice, you can implement non-dependent properties as member objects or as get/set methods.

As soon as you have defined the public interface of your method, I would try starting to think about how to implement it. Note that memory management of Matlab and C++ is different (Matlab uses Copy on Write and cares about memory management, none of this exists in pure C++). Also, caching of values (as is done with computeA and dependent properties) might be required in (slow object oriented) Matlab code but not necessarily in C++. To avoid premature optimization, why not just do:

class Foo {
    public:
      ClassB B;
      virtual ClassA getA() = 0;
      //define a setA()=0 if you need it here
    protected:
         //I wouldn't force subclasses to have the "caching" of dependent properties, so no virtual void computeA() = 0; 
         Foo(ClassBar const& bar) { this.B = ClassB(bar); /*Note that SomeFoo cannot be assigned to B*/ }
}
class Subclass: public Foo {
    private:
        ClassA A;
    public:
        ClassA getA() { ClassA A; /*compute A*/ return A; } 
}

If you experience that the computation of A is too slow, you can still "locally cache A" in the Subclass:

class Subclass: public Foo {
    private:
        ClassA A;
    public:
        ClassA getA() { /*compute A if required*/ return A; } 
}

If you really want to store A in Foo, I'd rather implement it as

class Foo {
    private:
      ClassA A;
    public:
      ClassB B;
      ClassA getA() { if (!A.initialized) A=computeA(); return A; };
    protected:
         virtual ClassA computeA() = 0;
         Foo(ClassBar const& bar) { this.B = ClassB(bar); /*Note that SomeFoo cannot be assigned to B*/ }
}
class Subclass: public Foo {
    protected:             
         virtual ClassA computeA() {...}
}

And don't forget to always think about whether you actually want to pass by (const) reference or value...

Community
  • 1
  • 1
Philipp
  • 11,549
  • 8
  • 66
  • 126
  • 1
    I've carefully read this, and it seems that yours are all good suggestions that clarified most of the doubt I had. Thanks for your time :) – Alessandro L. Jan 18 '13 at 14:05