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. Managed C++/CLI
  4. Inheritance tricky question

Inheritance tricky question

Scheduled Pinned Locked Moved Managed C++/CLI
questionc++oophelp
4 Posts 2 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.
  • A Offline
    A Offline
    Amrit Agr
    wrote on last edited by
    #1

    Hi Friends, I came through a interesting question in inheritance. Here is the chunk of code and out put is given below. // Inheritance tricky.cpp : Defines the entry point for the console application. // class Foo { private: int i; public: Foo() { i = 0; } void geti() { cout << i << endl; } }; class Bar : public Foo { private: int j; public: Bar() { j = 1; } void getj() { cout << j << endl; } }; void display(Foo* obj, int ctr) { for (int i = 0; i < ctr; i++) { ((Foo*)obj + i)->geti(); } } int _tmain(int argc, _TCHAR* argv[]) { Foo myFoo[3]; display(myFoo, 3); Bar myBar[3]; display(myBar, 3); return 0; } and Output is 0 0 0 0 1 0 The first 3 line is 0 that's fine. But how the 2nd last is 1 ??? Is there is any way that I can get all 0 in output if I am still executing this code Bar myBar[3]; display(myBar, 3); PLease help me out. Thanks in Advance. Regards, Amrit

    S 1 Reply Last reply
    0
    • A Amrit Agr

      Hi Friends, I came through a interesting question in inheritance. Here is the chunk of code and out put is given below. // Inheritance tricky.cpp : Defines the entry point for the console application. // class Foo { private: int i; public: Foo() { i = 0; } void geti() { cout << i << endl; } }; class Bar : public Foo { private: int j; public: Bar() { j = 1; } void getj() { cout << j << endl; } }; void display(Foo* obj, int ctr) { for (int i = 0; i < ctr; i++) { ((Foo*)obj + i)->geti(); } } int _tmain(int argc, _TCHAR* argv[]) { Foo myFoo[3]; display(myFoo, 3); Bar myBar[3]; display(myBar, 3); return 0; } and Output is 0 0 0 0 1 0 The first 3 line is 0 that's fine. But how the 2nd last is 1 ??? Is there is any way that I can get all 0 in output if I am still executing this code Bar myBar[3]; display(myBar, 3); PLease help me out. Thanks in Advance. Regards, Amrit

      S Offline
      S Offline
      Sascha Lefevre
      wrote on last edited by
      #2

      myBar[1].i is still 0. The problem here is that you try to apply pointer-arithmetic to a base-class pointer. When you add 1 to Foo* obj in the loop in display(..), the pointer is increased by the size of Foo, because it's declared as a pointer to Foo. But it's actually (initially) pointing to instances of Bar, whose size is larger than that of Foo - so after adding 1 to the pointer, it points to some address still within the first instance of Bar, not to the second Bar. The output of 1 is whatever happens to be at the address where i should be if the pointer was valid. The closest thing you can do to make it work is to use pointers to pointers:

      void display2(Foo** obj, int ctr)
      {
      for (int i = 0; i < ctr; i++)
      {
      (*(obj + i))->geti();
      }
      }

      int _tmain(int argc, _TCHAR* argv[])
      {
      Foo myFoo[3];
      display(myFoo, 3);

      Bar myBar\[3\];
      Foo \*myBaz\[3\] = { &myBar\[0\], &myBar\[1\], &myBar\[2\] };
      display2(myBaz, 3);
      
      return 0;
      

      }

      If the brain were so simple we could understand it, we would be so simple we couldn't. — Lyall Watson

      A 1 Reply Last reply
      0
      • S Sascha Lefevre

        myBar[1].i is still 0. The problem here is that you try to apply pointer-arithmetic to a base-class pointer. When you add 1 to Foo* obj in the loop in display(..), the pointer is increased by the size of Foo, because it's declared as a pointer to Foo. But it's actually (initially) pointing to instances of Bar, whose size is larger than that of Foo - so after adding 1 to the pointer, it points to some address still within the first instance of Bar, not to the second Bar. The output of 1 is whatever happens to be at the address where i should be if the pointer was valid. The closest thing you can do to make it work is to use pointers to pointers:

        void display2(Foo** obj, int ctr)
        {
        for (int i = 0; i < ctr; i++)
        {
        (*(obj + i))->geti();
        }
        }

        int _tmain(int argc, _TCHAR* argv[])
        {
        Foo myFoo[3];
        display(myFoo, 3);

        Bar myBar\[3\];
        Foo \*myBaz\[3\] = { &myBar\[0\], &myBar\[1\], &myBar\[2\] };
        display2(myBaz, 3);
        
        return 0;
        

        }

        If the brain were so simple we could understand it, we would be so simple we couldn't. — Lyall Watson

        A Offline
        A Offline
        Amrit Agr
        wrote on last edited by
        #3

        Hi Sascha, I am not able to understand why we need to take address of Bar objects in line Foo *myBaz[3] = { &myBar[0], &myBar[1], &myBar[2] }; and why we need to pass to pass the address of myBaz to a Foo** ( Double Pointer )? How surprisingly its working fine now? One more thing I still didn't get it hpw it prints 1 for 2nd iteration of Bar object. If I am not wrong, even if we are passing Bar address to Foo pointer, it wil call the geti function of Foo only ? so It should print variable i value that is 0 ? Please clear my doubt. Thanks

        S 1 Reply Last reply
        0
        • A Amrit Agr

          Hi Sascha, I am not able to understand why we need to take address of Bar objects in line Foo *myBaz[3] = { &myBar[0], &myBar[1], &myBar[2] }; and why we need to pass to pass the address of myBaz to a Foo** ( Double Pointer )? How surprisingly its working fine now? One more thing I still didn't get it hpw it prints 1 for 2nd iteration of Bar object. If I am not wrong, even if we are passing Bar address to Foo pointer, it wil call the geti function of Foo only ? so It should print variable i value that is 0 ? Please clear my doubt. Thanks

          S Offline
          S Offline
          Sascha Lefevre
          wrote on last edited by
          #4

          Hi Amrit, I'll try to explain it with some diagrams. First, the simple case - you probably know this, but I'll show it for completeness. The class Foo has a single member of type int (int32), so it has a size of 4 bytes.

          # 3 instances of Foo in memory with a Foo* pointer pointing to it:

          Foo myFoo[3]; // in _tmain(..)

          Foo* ptr = myFoo; // calling display(..) (I renamed *obj to *ptr here)

          ptr ptr+1 ptr+2 // the loop in display(..)

          (100) (100+4) (100+8)

          | | |

          v v v

          Memory address: 100..103 104..107 108..111 // (artificially chosen address)

          Instance: --Foo1-- --Foo2-- --Foo3--

          Members: ---i---- ---i---- ---i----

          Now with the class Bar (8 bytes) and your original approach:

          # 3 instances of Bar in memory with a Foo* pointer pointing to it:

          Bar myBar[3]; // in _tmain(..)

          Foo* ptr = myBar; // calling display(..)

          ptr ptr+1 ptr+2 // the loop in display(..)

          (100) (100+4) (100+8) // here's why it doesn't work:

          | | | // ptr is Foo* so ptr+1 still means adding the size of Foo (4) !

          v v v

          Memory address: 100........107 108........115 116........123

          Instance: -----Bar1----- -----Bar2----- -----Bar3-----

          Members: ---i---___j___ ---i---___j___ ---i---___j___

          Value: 0 1 0 // and there's your strange output! ;-)

          And now with pointers to pointers. Let's say we're on a 32bit-system here, then a pointer has the size of 4 bytes (32 bit). So, when doing pointer arithmetic with pointers to pointers, adding 1 means always increasing its pointed-to-address by 4 bytes. It doesn't have anything to do with the size of the class that's being pointed to by the pointer that's being pointed to :-D

          # 3 instances of Bar in memory with a Foo** pointer pointing to Bar* pointers:

          Bar myBar[3]; // in _tmain(..)
          Foo *myBaz[3] = { &myBar[0], &myBar[1], &myBar[2] };

          Value: 100 108 116

          Foo** pptr = myBaz; // calling display2(..) (for clarity, I named it pptr here)

          pptr pptr+1 pptr+2

          (200) (200+4) (200+8) // see explanati

          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