I wish c++ did interfaces better.

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Chris Becke

    I wish c++ did interfaces better.

    Given an interface (in the c++ sense, nothing more than a struct containing pure virtual methods)

    struct Iv1 {
    virtual method0()=0; };

    And a class that implements the interface

    class Iv1Impl : public Iv1 {
    virtual method0(){...}
    }

    Its not unreasonable to create a version 2 interface

    struct Iv2 : Iv1 {
    virtual method1()=0;};

    One might *try* to create an implementation class like this

    class Iv2Impl : public Iv2, Iv1Impl {
    virtual method1(){...}; // implement Iv2 method
    };

    That of course never never never works. Why not? So what that Ive introduced another method0()=0 ? Why can't it figure out it already has an implementation for that method that I'd really like to allow it to use?



  • kwikius

    #2
    Re: I wish c++ did interfaces better.

    Chris Becke wrote:
    Given an interface (in the c++ sense, nothing more than a struct containing pure virtual methods)
    <...>
    That of course never never never works. Why not?
    So what that Ive introduced another method0()=0 ?
    Why can't it figure out it already has an implementation
    for that method that I'd really like to allow it to use?

    struct Iv1 {
    virtual void method0()=0;
    };

    //And a class that implements the interface

    class Iv1Impl : public virtual Iv1 {
    virtual void method0(){}
    };

    //Its not unreasonable to create a version 2 interface

    struct Iv2 : virtual Iv1 {
    virtual void method1()=0;};

    //One might *try* to create an implementation class like this

    class Iv2Impl : public Iv2, Iv1Impl {
    virtual void method1(){} // implement Iv2 method
    };

    int main()
    {
    Iv2Impl x;
    }

    regards
    Andy Little

    Comment

    • Chris Becke

      #3
      Re: I wish c++ did interfaces better.

      You know.
      That works.
      Im sure I tried virtual inheritance before and it did not work.
      Perhaps it collapsed because the compiler i tried with (VC++ 8) doesn't implement virtual base classes correctly, or perhaps there is something fundamental that goes wrong when one tries to mix in overridden and inherited methods.

      "kwikius" <andy@servocomm .freeserve.co.u kwrote in message news:48996a8a_1 @mk-nntp-2.news.uk.tisca li.com...
      Chris Becke wrote:
      >Given an interface (in the c++ sense, nothing more than a struct containing pure virtual methods)
      <...>
      >That of course never never never works. Why not?
      So what that Ive introduced another method0()=0 ?
      Why can't it figure out it already has an implementation
      for that method that I'd really like to allow it to use?

      struct Iv1 {
      virtual void method0()=0;
      };

      //And a class that implements the interface

      class Iv1Impl : public virtual Iv1 {
      virtual void method0(){}
      };

      //Its not unreasonable to create a version 2 interface

      struct Iv2 : virtual Iv1 {
      virtual void method1()=0;};

      //One might *try* to create an implementation class like this

      class Iv2Impl : public Iv2, Iv1Impl {
      virtual void method1(){} // implement Iv2 method
      };

      int main()
      {
      Iv2Impl x;
      }

      regards
      Andy Little

      Comment

      • kwikius

        #4
        Re: I wish c++ did interfaces better.

        Chris Becke wrote:
        You know.
        That works.
        Im sure I tried virtual inheritance before and it did not work.
        Perhaps it collapsed because the compiler i tried with (VC++ 8) doesn't implement virtual base classes correctly, or perhaps there is something fundamental that goes wrong when one tries to mix in overridden and inherited methods.
        Well.. I think I too know the "Doh..!" feeling... ;-)

        Example was tested in VC8 FWIW, maybe your version was being grumpy
        today. Mine does that sometimes. Compilers... Love em hate but cant do
        without em.

        regards
        Andy Little

        Comment

        • Stuart Golodetz

          #5
          Re: I wish c++ did interfaces better.

          kwikius wrote:
          Chris Becke wrote:
          >You know.
          >That works.
          >Im sure I tried virtual inheritance before and it did not work.
          >Perhaps it collapsed because the compiler i tried with (VC++ 8)
          >doesn't implement virtual base classes correctly, or perhaps there is
          >something fundamental that goes wrong when one tries to mix in
          >overridden and inherited methods.
          >
          Well.. I think I too know the "Doh..!" feeling... ;-)
          >
          Example was tested in VC8 FWIW, maybe your version was being grumpy
          today. Mine does that sometimes. Compilers... Love em hate but cant do
          without em.
          >
          regards
          Andy Little
          Sorry to piggy-back on this thread, but it reminded me of a related
          interfaces problem I had a while back actually (I found a way to
          circumvent it, but it was a bit unsatisfactory) .

          Suppose you're implementing an inheritance hierarchy of Cartesian
          coordinate systems. You start off with interfaces:

          ICoordSystem <-- IOrthogonalCoor dSystem <-- IOrthonormalCoo rdSystem

          You then want to implement each of these concretely:

          ICoordSystem <-- CoordSystem
          IOrthogonalCoor dSystem <-- OrthogonalCoord System
          IOrthonormalCoo rdSystem <-- OrthonormalCoor dSystem

          The only problem is, you want to reuse the logic in CoordSystem etc., so
          you also have this:

          CoordSystem <-- OrthogonalCoord System <-- OrthonormalCoor dSystem

          At this point, I started having fun with my compiler. It was a while
          back now, so I can't quite remember what I tried any more before giving
          up and doing it another way, but how should I have done it please, out
          of interest?

          I had come across virtual inheritance back then, but I clearly wasn't
          applying it as I should have been!

          Cheers,
          Stu

          Comment

          • Stuart Golodetz

            #6
            Re: I wish c++ did interfaces better.

            Stuart Golodetz wrote:
            kwikius wrote:
            >Chris Becke wrote:
            >>You know.
            >>That works.
            >>Im sure I tried virtual inheritance before and it did not work.
            >>Perhaps it collapsed because the compiler i tried with (VC++ 8)
            >>doesn't implement virtual base classes correctly, or perhaps there is
            >>something fundamental that goes wrong when one tries to mix in
            >>overridden and inherited methods.
            >>
            >Well.. I think I too know the "Doh..!" feeling... ;-)
            >>
            >Example was tested in VC8 FWIW, maybe your version was being grumpy
            >today. Mine does that sometimes. Compilers... Love em hate but cant do
            >without em.
            >>
            >regards
            >Andy Little
            >
            Sorry to piggy-back on this thread, but it reminded me of a related
            interfaces problem I had a while back actually (I found a way to
            circumvent it, but it was a bit unsatisfactory) .
            >
            Suppose you're implementing an inheritance hierarchy of Cartesian
            coordinate systems. You start off with interfaces:
            >
            ICoordSystem <-- IOrthogonalCoor dSystem <-- IOrthonormalCoo rdSystem
            (And when I say interfaces, I mean interface classes... I really am
            talking about C++ here :-) Though the code was being ported from Java,
            which is why I encountered this sort of problem.)
            You then want to implement each of these concretely:
            >
            ICoordSystem <-- CoordSystem
            IOrthogonalCoor dSystem <-- OrthogonalCoord System
            IOrthonormalCoo rdSystem <-- OrthonormalCoor dSystem
            >
            The only problem is, you want to reuse the logic in CoordSystem etc., so
            you also have this:
            >
            CoordSystem <-- OrthogonalCoord System <-- OrthonormalCoor dSystem
            >
            At this point, I started having fun with my compiler. It was a while
            back now, so I can't quite remember what I tried any more before giving
            up and doing it another way, but how should I have done it please, out
            of interest?
            >
            I had come across virtual inheritance back then, but I clearly wasn't
            applying it as I should have been!
            >
            Cheers,
            Stu

            Comment

            • Stuart Golodetz

              #7
              Re: I wish c++ did interfaces better.

              Stuart Golodetz wrote:
              Stuart Golodetz wrote:
              >kwikius wrote:
              >>Chris Becke wrote:
              >>>You know.
              >>>That works.
              >>>Im sure I tried virtual inheritance before and it did not work.
              >>>Perhaps it collapsed because the compiler i tried with (VC++ 8)
              >>>doesn't implement virtual base classes correctly, or perhaps there
              >>>is something fundamental that goes wrong when one tries to mix in
              >>>overridden and inherited methods.
              >>>
              >>Well.. I think I too know the "Doh..!" feeling... ;-)
              >>>
              >>Example was tested in VC8 FWIW, maybe your version was being grumpy
              >>today. Mine does that sometimes. Compilers... Love em hate but cant
              >>do without em.
              >>>
              >>regards
              >>Andy Little
              >>
              >Sorry to piggy-back on this thread, but it reminded me of a related
              >interfaces problem I had a while back actually (I found a way to
              >circumvent it, but it was a bit unsatisfactory) .
              >>
              >Suppose you're implementing an inheritance hierarchy of Cartesian
              >coordinate systems. You start off with interfaces:
              >>
              >ICoordSystem <-- IOrthogonalCoor dSystem <-- IOrthonormalCoo rdSystem
              >
              (And when I say interfaces, I mean interface classes... I really am
              talking about C++ here :-) Though the code was being ported from Java,
              which is why I encountered this sort of problem.)
              >
              >You then want to implement each of these concretely:
              >>
              >ICoordSystem <-- CoordSystem
              >IOrthogonalCoo rdSystem <-- OrthogonalCoord System
              >IOrthonormalCo ordSystem <-- OrthonormalCoor dSystem
              >>
              >The only problem is, you want to reuse the logic in CoordSystem etc.,
              >so you also have this:
              >>
              >CoordSystem <-- OrthogonalCoord System <-- OrthonormalCoor dSystem
              >>
              >At this point, I started having fun with my compiler. It was a while
              >back now, so I can't quite remember what I tried any more before
              >giving up and doing it another way, but how should I have done it
              >please, out of interest?
              >>
              >I had come across virtual inheritance back then, but I clearly wasn't
              >applying it as I should have been!
              >>
              >Cheers,
              >Stu
              Ok, I've recreated the problem:

              struct I1
              {
              virtual void f() = 0;
              };

              struct I2 : virtual I1
              {
              virtual void g() = 0;
              };

              struct I3 : virtual I2
              {
              virtual void h() = 0;
              };

              struct C1 : virtual I1
              {
              void f()
              {
              std::cout << "f()" << std::endl;
              }
              };

              struct C2 : C1, virtual I2
              {
              void g()
              {
              std::cout << "g()" << std::endl;
              }
              };

              struct C3 : C2, I3
              {
              void h()
              {
              std::cout << "h()" << std::endl;
              }
              };

              When I do this, I get compiler warnings:

              Warning 1 warning C4250: 'C2' : inherits 'C1::C1::f' via dominance
              Warning 2 warning C4250: 'C3' : inherits 'C1::C1::f' via dominance
              Warning 3 warning C4250: 'C3' : inherits 'C2::C2::g' via dominance

              Please can someone explain what's going on?

              Cheers!
              Stu

              Comment

              • Pete Becker

                #8
                Re: I wish c++ did interfaces better.

                On 2008-08-06 20:51:21 -0400, Stuart Golodetz
                <sgolodetz@NdOi SaPlA.pMiPpLeEx A.ScEomsaid:
                >
                Ok, I've recreated the problem:
                >
                struct I1
                {
                virtual void f() = 0;
                };
                >
                struct I2 : virtual I1
                {
                virtual void g() = 0;
                };
                >
                struct C1 : virtual I1
                {
                void f()
                {
                std::cout << "f()" << std::endl;
                }
                };
                >
                struct C2 : C1, virtual I2
                {
                void g()
                {
                std::cout << "g()" << std::endl;
                }
                };
                [example simplified]
                >
                When I do this, I get compiler warnings:
                >
                Warning 1 warning C4250: 'C2' : inherits 'C1::C1::f' via dominance
                [additional warnings elided]
                >
                >
                Please can someone explain what's going on?
                >
                The compiler is warning you that it's doing what the language
                definition says it should do, and that you might not be smart enough to
                understand what you've done. But you are: the code is exactly right.

                Here's what's going on: C2 sees two definitons of f, one from C1 and
                one from i2 (which inherits it from i1). That would be ambiguous if it
                weren't for the dominance rule. Both C1 and i2 have i1 as a virtual
                base, so they both see the declaration of i1::f. C1 overrides i1::f,
                and i2 does not override it. C2 inherits from both, and the dominance
                rule says that a call to f on a C2 object is not ambiguous and calls
                C1::f. The definition of f that's nearer to C2 in the hierarchy
                dominates the one that's farther away. This rule only applies when all
                the inheritance paths lead to a common virtual base type that declares
                the function and only one of those paths has an overriding declaration.
                So if i2 also defined f, the call from C2 would be ambiguous. Got it?
                <g>

                --
                Pete
                Roundhouse Consulting, Ltd. (www.versatilecoding.com) Author of "The
                Standard C++ Library Extensions: a Tutorial and Reference
                (www.petebecker.com/tr1book)

                Comment

                • Francis Litterio

                  #9
                  Re: I wish c++ did interfaces better.

                  Stuart Golodetz wrote:
                  Ok, I've recreated the problem:
                  >
                  struct I1
                  {
                  virtual void f() = 0;
                  };
                  >
                  struct I2 : virtual I1
                  {
                  virtual void g() = 0;
                  };
                  >
                  struct I3 : virtual I2
                  {
                  virtual void h() = 0;
                  };
                  >
                  struct C1 : virtual I1
                  {
                  void f()
                  {
                  std::cout << "f()" << std::endl;
                  }
                  };
                  >
                  struct C2 : C1, virtual I2
                  {
                  void g()
                  {
                  std::cout << "g()" << std::endl;
                  }
                  };
                  >
                  struct C3 : C2, I3
                  {
                  void h()
                  {
                  std::cout << "h()" << std::endl;
                  }
                  };
                  >
                  When I do this, I get compiler warnings:
                  >
                  Warning 1 warning C4250: 'C2' : inherits 'C1::C1::f' via dominance
                  Warning 2 warning C4250: 'C3' : inherits 'C1::C1::f' via dominance
                  Warning 3 warning C4250: 'C3' : inherits 'C2::C2::g' via dominance
                  >
                  Please can someone explain what's going on?
                  C++ dominance: http://en.wikipedia.org/wiki/Dominance_(C%2B%2B)
                  --
                  Fran

                  Comment

                  • James Kanze

                    #10
                    Re: I wish c++ did interfaces better.

                    On Aug 7, 2:35 am, Stuart Golodetz
                    <sgolod...@NdOi SaPlA.pMiPpLeEx A.ScEomwrote:
                    Sorry to piggy-back on this thread, but it reminded me of a
                    related interfaces problem I had a while back actually (I
                    found a way to circumvent it, but it was a bit
                    unsatisfactory) .
                    Suppose you're implementing an inheritance hierarchy of
                    Cartesian coordinate systems. You start off with interfaces:
                    ICoordSystem <-- IOrthogonalCoor dSystem <-- IOrthonormalCoo rdSystem
                    You then want to implement each of these concretely:
                    ICoordSystem <-- CoordSystem
                    IOrthogonalCoor dSystem <-- OrthogonalCoord System
                    IOrthonormalCoo rdSystem <-- OrthonormalCoor dSystem
                    The only problem is, you want to reuse the logic in
                    CoordSystem etc., so you also have this:
                    CoordSystem <-- OrthogonalCoord System <-- OrthonormalCoor dSystem
                    At this point, I started having fun with my compiler. It was a
                    while back now, so I can't quite remember what I tried any
                    more before giving up and doing it another way, but how should
                    I have done it please, out of interest?
                    This is a classical case; I've seen it both with interfaces (as
                    in your example), and with machine generated code instead of
                    your interfaces (the machine generated code provides a simple,
                    default implementation, which you can override). I call it a
                    "ladder hierarchy", although I don't think I've seen this term
                    elsewhere:

                    ICoordSystem <--- CoordSystem
                    ^ ^
                    | |
                    | |
                    IOrthogonalCoor dSystem <--- OrthogonalCoord System
                    ^ ^
                    | |
                    | |
                    IOrthonormalCoo rdSystem <--- OrthonormalCoor dSystem

                    (Except that in one case I encountered, it extended some six or
                    seven layers deep.)

                    Basically, anytime a class has more than one arrow leading into
                    it, inheritance must be virtual; the simplest solution is just
                    to make all heritage of the interface virtual:

                    class ICoordSystem { /* ... */ } ;
                    class IOrthogonalCoor dSystem
                    : public virtual ICoordSystem { /* ... */ } ;
                    class IOrthonormalCoo rdSystem
                    : public virtual IOrthogonalCoor dSystem { /* ... */ } ;
                    class CoordSystem
                    : public virtual ICoordSystem { /* ... */ } ;
                    class OrthogonalCoord System
                    : public virtual IOrthogonalCoor dSystem
                    : private CoordSystem { /* ... */ } ;
                    class OrthonormalCoor dSystem
                    : public virtual IOrthonormalCoo rdSystem
                    : private OrthogonalCoord System { /* ... */ } ;

                    (Note that the inheritance of the implementation is private.
                    This is usual as well, although not always necessary.)

                    --
                    James Kanze (GABI Software) email:james.kan ze@gmail.com
                    Conseils en informatique orientée objet/
                    Beratung in objektorientier ter Datenverarbeitu ng
                    9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

                    Comment

                    • James Kanze

                      #11
                      Re: I wish c++ did interfaces better.

                      On Aug 7, 3:30 am, Pete Becker <p...@versatile coding.comwrote :
                      On 2008-08-06 20:51:21 -0400, Stuart Golodetz
                      <sgolod...@NdOi SaPlA.pMiPpLeEx A.ScEomsaid:
                      [...]
                      When I do this, I get compiler warnings:
                      Warning 1 warning C4250: 'C2' : inherits 'C1::C1::f' via dominance
                      Please can someone explain what's going on?
                      The compiler is warning you that it's doing what the language
                      definition says it should do, and that you might not be smart
                      enough to understand what you've done. But you are: the code
                      is exactly right.
                      But isn't this a stupid warning? The formal specification of
                      dominance might be a little complicated (but only a very
                      little), but in practice, it always does exactly what one would
                      intuitively expect and want. While I can see the compiler
                      warning when the standard requires it to do something you likely
                      don't want, or even when it isn't clear what you might want
                      (what happens when comparing signed and unsigned, for example),
                      this looks to me very close to warning that the generated code
                      will do an addition, because you used the + operator.

                      --
                      James Kanze (GABI Software) email:james.kan ze@gmail.com
                      Conseils en informatique orientée objet/
                      Beratung in objektorientier ter Datenverarbeitu ng
                      9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

                      Comment

                      • Pete Becker

                        #12
                        Re: I wish c++ did interfaces better.

                        On 2008-08-07 04:41:42 -0400, James Kanze <james.kanze@gm ail.comsaid:
                        On Aug 7, 3:30 am, Pete Becker <p...@versatile coding.comwrote :
                        >On 2008-08-06 20:51:21 -0400, Stuart Golodetz
                        ><sgolod...@NdO iSaPlA.pMiPpLeE xA.ScEomsaid:
                        >
                        [...]
                        >>When I do this, I get compiler warnings:
                        >
                        >>Warning 1 warning C4250: 'C2' : inherits 'C1::C1::f' via domin
                        ance
                        >
                        >>Please can someone explain what's going on?
                        >
                        >The compiler is warning you that it's doing what the language
                        >definition says it should do, and that you might not be smart
                        >enough to understand what you've done. But you are: the code
                        >is exactly right.
                        >
                        But isn't this a stupid warning?
                        Yes. My original draft started out "Stupid compiler warnings."
                        The formal specification of
                        dominance might be a little complicated (but only a very
                        little), but in practice, it always does exactly what one would
                        intuitively expect and want. While I can see the compiler
                        warning when the standard requires it to do something you likely
                        don't want, or even when it isn't clear what you might want
                        (what happens when comparing signed and unsigned, for example),
                        this looks to me very close to warning that the generated code
                        will do an addition, because you used the + operator.
                        Maybe it means "we worked really hard to understand and implement
                        dominance, so we want to make sure you notice it".

                        --
                        Pete
                        Roundhouse Consulting, Ltd. (www.versatilecoding.com) Author of "The
                        Standard C++ Library Extensions: a Tutorial and Reference
                        (www.petebecker.com/tr1book)

                        Comment

                        • Joe Greer

                          #13
                          Re: I wish c++ did interfaces better.

                          Pete Becker <pete@versatile coding.comwrote in
                          news:2008080706 140516807-pete@versatilec odingcom:
                          >
                          Maybe it means "we worked really hard to understand and implement
                          dominance, so we want to make sure you notice it".
                          >
                          It probably means that they have gotten a lot of bug reports about this
                          feature and they are doing a CYA manuver. :)

                          joe

                          Comment

                          • Chris Becke

                            #14
                            Re: I wish c++ did interfaces better.

                            struct Iv2 : virtual Iv1 {
                            virtual void method1()=0;};
                            Actually, this is where the house of cards falls down :- In a framework that uses interfaces to facilitate communication between precompiled modules potentially written in different languages you cannot ever use 'virtual' to extend an interface. The final resulting vtables MUST be contiguous in memory and using virtual will fragment them. :-(

                            "kwikius" <andy@servocomm .freeserve.co.u kwrote in message news:48996a8a_1 @mk-nntp-2.news.uk.tisca li.com...
                            Chris Becke wrote:
                            >Given an interface (in the c++ sense, nothing more than a struct containing pure virtual methods)
                            <...>
                            >That of course never never never works. Why not?
                            So what that Ive introduced another method0()=0 ?
                            Why can't it figure out it already has an implementation
                            for that method that I'd really like to allow it to use?

                            struct Iv1 {
                            virtual void method0()=0;
                            };

                            //And a class that implements the interface

                            class Iv1Impl : public virtual Iv1 {
                            virtual void method0(){}
                            };

                            //Its not unreasonable to create a version 2 interface

                            struct Iv2 : virtual Iv1 {
                            virtual void method1()=0;};

                            //One might *try* to create an implementation class like this

                            class Iv2Impl : public Iv2, Iv1Impl {
                            virtual void method1(){} // implement Iv2 method
                            };

                            int main()
                            {
                            Iv2Impl x;
                            }

                            regards
                            Andy Little

                            Comment

                            • Pete Becker

                              #15
                              Re: I wish c++ did interfaces better.

                              On 2008-08-07 10:09:29 -0400, "Chris Becke" <chris.becke@gm ail.comsaid:
                              >struct Iv2 : virtual Iv1 {
                              >virtual void method1()=0;};
                              >
                              Actually, this is where the house of cards falls down :- In a framework
                              that uses interfaces to facilitate communication between precompiled
                              modules potentially written in different languages you cannot ever use
                              'virtual' to extend an interface. The final resulting vtables MUST be
                              contiguous in memory and using virtual will fragment them. :-(
                              Huh? If you don't use virtuals you won't get vtables. Unless by
                              "vtable" you mean some non-C++ interoperabilit y mechanism, in which
                              case, it's not particularly pertinent here.

                              --
                              Pete
                              Roundhouse Consulting, Ltd. (www.versatilecoding.com) Author of "The
                              Standard C++ Library Extensions: a Tutorial and Reference
                              (www.petebecker.com/tr1book)

                              Comment

                              Working...