Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. C / C++ / MFC
  4. Ambiguity of 'this' and 'member function' [modified]

Ambiguity of 'this' and 'member function' [modified]

Scheduled Pinned Locked Moved C / C++ / MFC
questionc++helplearning
7 Posts 3 Posters 0 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • D Offline
    D Offline
    Dean Seo
    wrote on last edited by
    #1

    This code below occurs no error but the result seems a bit weird.

    class KBase
    {
    public:
    void BaseFun()
    {
    printf( "KBase::BaseFun() this=%p\n", this );
    }
    };

    class KMiddle : public KBase
    {
    };

    class KMiddle2 : public KBase
    {
    };

    class KDerived : public KMiddle, public KMiddle2
    {
    };

    int main()
    {
    KDerived d;

    d.KBase::BaseFun();   // 0012FF63
    d.KMiddle::BaseFun();  // 0012FF63
    d.KMiddle2::BaseFun();  // 0012FF64 ??
    
    return 0;
    

    }//main()

    BaseFun simply shows this pointer and the result goes.. --------------------------- KBase::BaseFun() this=0012FF63 KBase::BaseFun() this=0012FF63 KBase::BaseFun() this=0012FF64 --------------------------- So my question is why KBase::BaseFun() and KMiddle::BaseFun() show the same address and the only KMiddle2::BaseFun() does the different address? I was looking for the answer by reading Stephen Prata's book and Effective C++ but I couldn't. Thanks in advance.

    modified on Wednesday, August 24, 2011 9:51 PM

    X C 2 Replies Last reply
    0
    • D Dean Seo

      This code below occurs no error but the result seems a bit weird.

      class KBase
      {
      public:
      void BaseFun()
      {
      printf( "KBase::BaseFun() this=%p\n", this );
      }
      };

      class KMiddle : public KBase
      {
      };

      class KMiddle2 : public KBase
      {
      };

      class KDerived : public KMiddle, public KMiddle2
      {
      };

      int main()
      {
      KDerived d;

      d.KBase::BaseFun();   // 0012FF63
      d.KMiddle::BaseFun();  // 0012FF63
      d.KMiddle2::BaseFun();  // 0012FF64 ??
      
      return 0;
      

      }//main()

      BaseFun simply shows this pointer and the result goes.. --------------------------- KBase::BaseFun() this=0012FF63 KBase::BaseFun() this=0012FF63 KBase::BaseFun() this=0012FF64 --------------------------- So my question is why KBase::BaseFun() and KMiddle::BaseFun() show the same address and the only KMiddle2::BaseFun() does the different address? I was looking for the answer by reading Stephen Prata's book and Effective C++ but I couldn't. Thanks in advance.

      modified on Wednesday, August 24, 2011 9:51 PM

      X Offline
      X Offline
      xrg_soft 163 com
      wrote on last edited by
      #2

      Which complier do you use? in some complier that follow the standard c++ strictly, like g++, your code will not compiled and got Error Message: `D' is an ambiguous base of `B' To make the multiple inheritance follows the standard c++ well, you should using virtual inheritance in this case.

      class KMiddle : virtual public KBase
      class KMiddle2 : virtual public KBase

      class KDerived : public KMiddle, public KMiddle2

      D 1 Reply Last reply
      0
      • X xrg_soft 163 com

        Which complier do you use? in some complier that follow the standard c++ strictly, like g++, your code will not compiled and got Error Message: `D' is an ambiguous base of `B' To make the multiple inheritance follows the standard c++ well, you should using virtual inheritance in this case.

        class KMiddle : virtual public KBase
        class KMiddle2 : virtual public KBase

        class KDerived : public KMiddle, public KMiddle2

        D Offline
        D Offline
        Dean Seo
        wrote on last edited by
        #3

        Hi,

        xrg_soft@163.com wrote:

        Which complier do you use?

        I use Visual Studio 2008.

        xrg_soft@163.com wrote:

        To make the multiple inheritance follows the standard c++ well, you should using virtual inheritance

        I know that the multiple inheritance needs virtual inheritance. However, when I don't on purpose, the result seems not understandable. Could you explain to me why those 'this' addresses look unrestrained?

        X 1 Reply Last reply
        0
        • D Dean Seo

          This code below occurs no error but the result seems a bit weird.

          class KBase
          {
          public:
          void BaseFun()
          {
          printf( "KBase::BaseFun() this=%p\n", this );
          }
          };

          class KMiddle : public KBase
          {
          };

          class KMiddle2 : public KBase
          {
          };

          class KDerived : public KMiddle, public KMiddle2
          {
          };

          int main()
          {
          KDerived d;

          d.KBase::BaseFun();   // 0012FF63
          d.KMiddle::BaseFun();  // 0012FF63
          d.KMiddle2::BaseFun();  // 0012FF64 ??
          
          return 0;
          

          }//main()

          BaseFun simply shows this pointer and the result goes.. --------------------------- KBase::BaseFun() this=0012FF63 KBase::BaseFun() this=0012FF63 KBase::BaseFun() this=0012FF64 --------------------------- So my question is why KBase::BaseFun() and KMiddle::BaseFun() show the same address and the only KMiddle2::BaseFun() does the different address? I was looking for the answer by reading Stephen Prata's book and Effective C++ but I couldn't. Thanks in advance.

          modified on Wednesday, August 24, 2011 9:51 PM

          C Offline
          C Offline
          CPallini
          wrote on last edited by
          #4

          From "Diamond problem" at Wikipedia[^]:

          C++ by default follows each inheritance path separately, so a D object would actually contain two separate A objects, and uses of A's members have to be properly qualified. If the inheritance from A to B and the inheritance from A to C are both marked "virtual" (for example, "class B : virtual public A"), C++ takes special care to only create one A object, and uses of A's members work correctly. If virtual inheritance and nonvirtual inheritance are mixed, there is a single virtual A and a nonvirtual A for each nonvirtual inheritance path to A. Please note that nonvirtual derivation of A in this case will be useless as direct access to any part of class A from class D will practically always end up with compile error.

          If the Lord God Almighty had consulted me before embarking upon the Creation, I would have recommended something simpler. -- Alfonso the Wise, 13th Century King of Castile.
          This is going on my arrogant assumptions. You may have a superb reason why I'm completely wrong. -- Iain Clarke
          [My articles]

          D 1 Reply Last reply
          0
          • D Dean Seo

            Hi,

            xrg_soft@163.com wrote:

            Which complier do you use?

            I use Visual Studio 2008.

            xrg_soft@163.com wrote:

            To make the multiple inheritance follows the standard c++ well, you should using virtual inheritance

            I know that the multiple inheritance needs virtual inheritance. However, when I don't on purpose, the result seems not understandable. Could you explain to me why those 'this' addresses look unrestrained?

            X Offline
            X Offline
            xrg_soft 163 com
            wrote on last edited by
            #5

            In your case(no virtual inheritance used), the The inside of the KDrived object, there is a KMiddle object followed by a KMiddle2 object. d.KBase::BaseFun(); d.KMiddle::BaseFun(); actually calls to the function of the KMiddle object. and d.KMiddle2::BaseFun(); calls to the function of the KMiddle2 object. As your Kxxx object contains nothing, so sizeof(Kxxx) == 1 That's why the result printed. And if you adding somemember variable into the class, then the result should be: KBase::BaseFun() this= KBase::BaseFun() this= KBase::BaseFun() this=<base> + sizeof(KMiddle)

            D 1 Reply Last reply
            0
            • X xrg_soft 163 com

              In your case(no virtual inheritance used), the The inside of the KDrived object, there is a KMiddle object followed by a KMiddle2 object. d.KBase::BaseFun(); d.KMiddle::BaseFun(); actually calls to the function of the KMiddle object. and d.KMiddle2::BaseFun(); calls to the function of the KMiddle2 object. As your Kxxx object contains nothing, so sizeof(Kxxx) == 1 That's why the result printed. And if you adding somemember variable into the class, then the result should be: KBase::BaseFun() this= KBase::BaseFun() this= KBase::BaseFun() this=<base> + sizeof(KMiddle)

              D Offline
              D Offline
              Dean Seo
              wrote on last edited by
              #6

              Thank you so much!! I truly appreciate it!

              1 Reply Last reply
              0
              • C CPallini

                From "Diamond problem" at Wikipedia[^]:

                C++ by default follows each inheritance path separately, so a D object would actually contain two separate A objects, and uses of A's members have to be properly qualified. If the inheritance from A to B and the inheritance from A to C are both marked "virtual" (for example, "class B : virtual public A"), C++ takes special care to only create one A object, and uses of A's members work correctly. If virtual inheritance and nonvirtual inheritance are mixed, there is a single virtual A and a nonvirtual A for each nonvirtual inheritance path to A. Please note that nonvirtual derivation of A in this case will be useless as direct access to any part of class A from class D will practically always end up with compile error.

                If the Lord God Almighty had consulted me before embarking upon the Creation, I would have recommended something simpler. -- Alfonso the Wise, 13th Century King of Castile.
                This is going on my arrogant assumptions. You may have a superb reason why I'm completely wrong. -- Iain Clarke
                [My articles]

                D Offline
                D Offline
                Dean Seo
                wrote on last edited by
                #7

                Thank you!

                1 Reply Last reply
                0
                Reply
                • Reply as topic
                Log in to reply
                • Oldest to Newest
                • Newest to Oldest
                • Most Votes


                • Login

                • Don't have an account? Register

                • Login or register to search.
                • First post
                  Last post
                0
                • Categories
                • Recent
                • Tags
                • Popular
                • World
                • Users
                • Groups