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. Other Discussions
  3. Clever Code
  4. duplicated member variables in derived classes

duplicated member variables in derived classes

Scheduled Pinned Locked Moved Clever Code
c++debugginghelpquestion
22 Posts 11 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.
  • J jhwurmbach

    bolivar123 wrote:

    Use of CArray vs. using std::vector has nothing to do with the point I was trying to make.

    Granted, but is is my habit to object against CArray whenever I see its use.:rolleyes: It was created with the early MFCs. Out of dire need when the MS-C++ was so fundamentally broken as being incapable of compiling any STL. There is no need to use the afxtempl.h-collections in new software! You are right with

    for (int i=0;imyType)
    {
    case TYPEA:
    DoSomethingWithTypeA(pA);
    break;
    case TYPEB:
    DoSomethingWithTypeB((B*)ptr);
    break;
    case TYPEC:
    DoSomethingWithTypeC((C*)ptr);
    break;
    }
    }

    pA->myType will always be TYPEA (or undefined, with your unmodified code from the first posting). I had been misled by the debugger (VC2003), which is capable of showing the virtual variable (TYPEB, TYPEC) when the mouse is hovering over pA. When hovering over pA->myType, the correct value is shown, though. This whole issue is one of the confusing points of the C++ typesystem, but not a subtle bug, I think. You ordered a A*, so you got an A*.


    "We trained hard, but it seemed that every time we were beginning to form up into teams we would be reorganised. I was to learn later in life that we tend to meet any new situation by reorganising: and a wonderful method it can be for creating the illusion of progress, while producing confusion, inefficiency and demoralisation." -- Caius Petronius, Roman Consul, 66 A.D.

    M Offline
    M Offline
    Mike ONeill
    wrote on last edited by
    #13

    jhwurmbach wrote:

    I had been misled by the debugger (VC2003), which is capable of showing the virtual variable (TYPEB, TYPEC) when the mouse is hovering over pA.

    What is a "virtual variable"? I don't think that there is any such beast. Mike

    J 1 Reply Last reply
    0
    • M Mike ONeill

      jhwurmbach wrote:

      I had been misled by the debugger (VC2003), which is capable of showing the virtual variable (TYPEB, TYPEC) when the mouse is hovering over pA.

      What is a "virtual variable"? I don't think that there is any such beast. Mike

      J Offline
      J Offline
      jhwurmbach
      wrote on last edited by
      #14

      Mike O`Neill wrote:

      What is a "virtual variable"? I don't think that there is any such beast.

      No - there isn't. Thats the point of this example. But the debugger shows - when the mouse hovers over pA - the value TYPEB or TYPEC for the variable myType - which is undefined, as the experiment with the switch/case shows. .


      "We trained hard, but it seemed that every time we were beginning to form up into teams we would be reorganised. I was to learn later in life that we tend to meet any new situation by reorganising: and a wonderful method it can be for creating the illusion of progress, while producing confusion, inefficiency and demoralisation." -- Caius Petronius, Roman Consul, 66 A.D.

      1 Reply Last reply
      0
      • B bolivar123

        Consider the following simple Win32 console app. It defines 3 classes A, B, and C. The classes B and C derive from class A. We create a CArray of class A pointers. Since B and C are derived from A, we can add pointers to B and C to the CArray. On the lines with "LINE A", "LINE B", and "LINE C" comments, what would the value of pA->myType be in each case? Hint, it won't be TYPEA, TYPEB, or TYPEC! To test this app, set breakpoints at each of the 3 lines with the calls to GetAt, and view the value of pA->myType in the debugger.

        // FooTest.cpp : Defines the entry point for the console application.
        //

        #include "stdafx.h"
        #include "FooTest.h"
        #include <afxtempl.h>

        #ifdef _DEBUG
        #define new DEBUG_NEW
        #endif

        // The one and only application object

        CWinApp theApp;

        using namespace std;

        enum TClassType {TYPEA, TYPEB, TYPEC};

        class A
        {
        public:
        A() {};
        ~A();
        TClassType myType;
        };

        class B : public A
        {
        public:
        B() { myType = TYPEB; }
        ~B();
        TClassType myType;
        };

        class C : public A
        {
        public:
        C() { myType = TYPEC; }
        ~C();
        TClassType myType;
        };

        int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
        {
        int nRetCode = 0;
        CArray<A*> myArray;
        A* pA;

        myArray.Add(new A);
        myArray.Add(new B);
        myArray.Add(new C);
         
        pA = myArray.GetAt(0); //LINE A
        pA = myArray.GetAt(1); //LINE B
        pA = myArray.GetAt(2); //LINE C
        
        
        // initialize MFC and print and error on failure
        if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0))
        {
        	// TODO: change error code to suit your needs
        	\_tprintf(\_T("Fatal Error: MFC initialization failed\\n"));
        	nRetCode = 1;
        }
        else
        {
        	// TODO: code your application's behavior here.
        }
        
        return nRetCode;
        

        }

        P Offline
        P Offline
        Pierre Leclercq
        wrote on last edited by
        #15

        <Not meaning to be mean> <But...> Well, not sure this belongs to subtle bugs. The repetition of the same variable names would push it to bad design. And the unitialized member variable in the base class pushes it to bad code. </...But> <Not even> Talking about the lack of virtual destructors in a class hierarchy. Or <Ksss...> The use of public member variable. </...Ksss> </Not even> </Not meaning to be mean> <Feels like...> X| </...Feels like>

        B 1 Reply Last reply
        0
        • B bolivar123

          Oh goodie! If they don't plan on changing CArray, I'll continue using it. I just hate it when they go changing a good thing. Like the changes in CString from MFC 6 to MFC 7. Geez, I didn't think the original post would tangent to a debate on which is better......

          K Offline
          K Offline
          Kevin McFarlane
          wrote on last edited by
          #16

          bolivar123 wrote:

          I didn't think the original post would tangent to a debate on which is better.....

          Yes, it shouldn't really have done this as, for example, even if STL is the recommended way you could quite validly have been maintaining legacy code. Nonetheless, as an aside, I agree with the other guys that, other things being equal, we should prefer the STL - certainly for new projects. It's not as though this stuff has only just come out. All experienced C++ developers should be comfortable enough with it by now. OTOH, I'm not that religious about it. For example, although I haven't done any MFC for ages, I did still prefer CString to string.

          Kevin

          1 Reply Last reply
          0
          • P Pierre Leclercq

            <Not meaning to be mean> <But...> Well, not sure this belongs to subtle bugs. The repetition of the same variable names would push it to bad design. And the unitialized member variable in the base class pushes it to bad code. </...But> <Not even> Talking about the lack of virtual destructors in a class hierarchy. Or <Ksss...> The use of public member variable. </...Ksss> </Not even> </Not meaning to be mean> <Feels like...> X| </...Feels like>

            B Offline
            B Offline
            bolivar123
            wrote on last edited by
            #17

            It is bad design and/or bad code for new developed code, but if you're cleaning up/encapsulating somebody else's code (who is no longer with the company)... BTW, does the incorrect use of XML tags make your post bad code?

            P P 2 Replies Last reply
            0
            • B bolivar123

              It is bad design and/or bad code for new developed code, but if you're cleaning up/encapsulating somebody else's code (who is no longer with the company)... BTW, does the incorrect use of XML tags make your post bad code?

              P Offline
              P Offline
              PIEBALDconsult
              wrote on last edited by
              #18

              I expect those will soon be Microsoft extensions to XML.

              B P 2 Replies Last reply
              0
              • P PIEBALDconsult

                I expect those will soon be Microsoft extensions to XML.

                B Offline
                B Offline
                bolivar123
                wrote on last edited by
                #19

                Until then, it'll be a not so subtle bug :laugh:

                1 Reply Last reply
                0
                • B bolivar123

                  It is bad design and/or bad code for new developed code, but if you're cleaning up/encapsulating somebody else's code (who is no longer with the company)... BTW, does the incorrect use of XML tags make your post bad code?

                  P Offline
                  P Offline
                  Pierre Leclercq
                  wrote on last edited by
                  #20

                  bolivar123 wrote:

                  incorrect use of XML tags

                  Are you talking about the "..."? That was done on purpose... But I'm sure you'll gladly encapsulate it into a new post :)

                  1 Reply Last reply
                  0
                  • P PIEBALDconsult

                    I expect those will soon be Microsoft extensions to XML.

                    P Offline
                    P Offline
                    Pierre Leclercq
                    wrote on last edited by
                    #21

                    Actually this is not XML, this an extension to plain English. :)

                    1 Reply Last reply
                    0
                    • B bolivar123

                      Consider the following simple Win32 console app. It defines 3 classes A, B, and C. The classes B and C derive from class A. We create a CArray of class A pointers. Since B and C are derived from A, we can add pointers to B and C to the CArray. On the lines with "LINE A", "LINE B", and "LINE C" comments, what would the value of pA->myType be in each case? Hint, it won't be TYPEA, TYPEB, or TYPEC! To test this app, set breakpoints at each of the 3 lines with the calls to GetAt, and view the value of pA->myType in the debugger.

                      // FooTest.cpp : Defines the entry point for the console application.
                      //

                      #include "stdafx.h"
                      #include "FooTest.h"
                      #include <afxtempl.h>

                      #ifdef _DEBUG
                      #define new DEBUG_NEW
                      #endif

                      // The one and only application object

                      CWinApp theApp;

                      using namespace std;

                      enum TClassType {TYPEA, TYPEB, TYPEC};

                      class A
                      {
                      public:
                      A() {};
                      ~A();
                      TClassType myType;
                      };

                      class B : public A
                      {
                      public:
                      B() { myType = TYPEB; }
                      ~B();
                      TClassType myType;
                      };

                      class C : public A
                      {
                      public:
                      C() { myType = TYPEC; }
                      ~C();
                      TClassType myType;
                      };

                      int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
                      {
                      int nRetCode = 0;
                      CArray<A*> myArray;
                      A* pA;

                      myArray.Add(new A);
                      myArray.Add(new B);
                      myArray.Add(new C);
                       
                      pA = myArray.GetAt(0); //LINE A
                      pA = myArray.GetAt(1); //LINE B
                      pA = myArray.GetAt(2); //LINE C
                      
                      
                      // initialize MFC and print and error on failure
                      if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0))
                      {
                      	// TODO: change error code to suit your needs
                      	\_tprintf(\_T("Fatal Error: MFC initialization failed\\n"));
                      	nRetCode = 1;
                      }
                      else
                      {
                      	// TODO: code your application's behavior here.
                      }
                      
                      return nRetCode;
                      

                      }

                      B Offline
                      B Offline
                      Bernodus Kristinsson
                      wrote on last edited by
                      #22

                      The value-of pA->myType is the value-of pA->A::myType which has not been initialized. Some changes: class A {public: A(){/*myType = TYPEA;*/} ~A(){} TClassType myType;}; class B : public A {public: B(){ myType = TYPEB; } ~B(){} TClassType myType;}; class C : public A {public: C(){ myType = TYPEC; } ~C(){} int myType;}; A* pA; B* pB; C* pC; pA = myArray.GetAt(0); //LINE A pA = myArray.GetAt(1); //LINE B pB = (B*)pA; TClassType eAB = pB->myType; TClassType eAA = pB->A::myType; pA = myArray.GetAt(2); //LINE C pC = (C*)pA; TClassType eAC = TClassType)pC->myType; eAA = pC->A::myType; Results: TYPEB == pB->myType // B::myType 2 == pC->myType // C::myType, 2==TYPEC ? == pA->myType // A::myType when uninitialized TYPEA == pA->myType // A::myType when initializion is uncommented Comments: Data-members are hidden or overridden. "Plain" function-members are hidden or overridden. Virtual function-members are virtual (behavior you expected). Hiding/overriding depends on NAME not type (see TClassType versus int). More comments: Such hiding is probably most often not done on purpose. Therefore Hiding data-members is 99.9999% (sure to result in) a bug. Hiding function-members is 99% a bug.

                      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