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.
  • 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;
    

    }

    C Offline
    C Offline
    Chris Meech
    wrote on last edited by
    #2

    It won't be TYPEA, or TYPEB, or TYPEC. The pointer is of Type A, but since it's myType member variable is never initialised, the value of pA->myType will be who knows what. :)

    Chris Meech I am Canadian. [heard in a local bar] I agree with you that my argument is useless. [Red Stateler] Hey, I am part of a special bread, we are called smart people [Captain See Sharp] The zen of the soapbox is hard to attain...[Jörgen Sigvardsson] I wish I could remember what it was like to only have a short term memory.[David Kentley]

    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;
      

      }

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

      CArray is X| There is std::vector, and since VC6 it is actually working. Use virtuality when you need it. Especially the lack of virtual d'tors would get you a hard time over here... And with providing a virtual d'tor, you get rid of these annoying effects. The lack of myType-Initialisation in A was deliberately?!?

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

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

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


      "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.

      B 1 Reply Last reply
      0
      • J jhwurmbach

        CArray is X| There is std::vector, and since VC6 it is actually working. Use virtuality when you need it. Especially the lack of virtual d'tors would get you a hard time over here... And with providing a virtual d'tor, you get rid of these annoying effects. The lack of myType-Initialisation in A was deliberately?!?

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

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

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


        "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.

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

        Use of CArray vs. using std::vector has nothing to do with the point I was trying to make. Even with the virtual destructor and with an initialization of myType in the A constructor, the effect would still be the same in the B and C case. Suppose we were iterating over all of the elements in myArray and examining the value of myType hoping to figure out what class type we would need to cast the pointer returned in the call to GetAt. myArray.Add(new A); myArray.Add(new B); myArray.Add(new C); for (int i=0;imyType) { case TYPEA: DoSomethingWithTypeA(pA); break; case TYPEB: DoSomethingWithTypeB((B*)ptr); break; case TYPEC: DoSomethingWithTypeC((C*)ptr); break; } } You would never see a call to DoSomethingWithTypeB or DoSomethingWithTypeC, even though element 1 is type B and element 2 is type C. I agree with your comment of using virtual functions and/or destructors. A better way to do this, would be to use a virtual function to do whatever would be done in the respective DoSomethingWith-- calls. Like this: // FooTest.cpp : Defines the entry point for the console application. // #include "stdafx.h" #include class A { public: A() {}; virtual ~A(){}; virtual void DoSomething(); }; class B : public A { public: B() {} virtual ~B() {}; virtual void DoSomething(); }; class C : public A { public: C() {} virtual ~C() {}; virtual void DoSomething(); }; void A::DoSomething() { //Do something with type A } void B::DoSomething() { //Do something with type B } void C::DoSomething() { //Do something with type C } int _tmain(int argc, _TCHAR* argv[]) { CArray myArray; myArray.Add(new A); myArray.Add(new B); myArray.Add(new C); for (int i=0;iDoSomething(); } //Get rid of the memory leak so as to avoid getting a bunch of bad style comments for (int i=0;i

        J 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;
          

          }

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

          That is an issue, but it is also, I think, a bad design of the class hierarchy. :)

          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.

          B 1 Reply Last reply
          0
          • B bolivar123

            Use of CArray vs. using std::vector has nothing to do with the point I was trying to make. Even with the virtual destructor and with an initialization of myType in the A constructor, the effect would still be the same in the B and C case. Suppose we were iterating over all of the elements in myArray and examining the value of myType hoping to figure out what class type we would need to cast the pointer returned in the call to GetAt. myArray.Add(new A); myArray.Add(new B); myArray.Add(new C); for (int i=0;imyType) { case TYPEA: DoSomethingWithTypeA(pA); break; case TYPEB: DoSomethingWithTypeB((B*)ptr); break; case TYPEC: DoSomethingWithTypeC((C*)ptr); break; } } You would never see a call to DoSomethingWithTypeB or DoSomethingWithTypeC, even though element 1 is type B and element 2 is type C. I agree with your comment of using virtual functions and/or destructors. A better way to do this, would be to use a virtual function to do whatever would be done in the respective DoSomethingWith-- calls. Like this: // FooTest.cpp : Defines the entry point for the console application. // #include "stdafx.h" #include class A { public: A() {}; virtual ~A(){}; virtual void DoSomething(); }; class B : public A { public: B() {} virtual ~B() {}; virtual void DoSomething(); }; class C : public A { public: C() {} virtual ~C() {}; virtual void DoSomething(); }; void A::DoSomething() { //Do something with type A } void B::DoSomething() { //Do something with type B } void C::DoSomething() { //Do something with type C } int _tmain(int argc, _TCHAR* argv[]) { CArray myArray; myArray.Add(new A); myArray.Add(new B); myArray.Add(new C); for (int i=0;iDoSomething(); } //Get rid of the memory leak so as to avoid getting a bunch of bad style comments for (int i=0;i

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

            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.

            B Z M 3 Replies Last reply
            0
            • 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.

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

              Previous versions of MFC had a CArray class and different variants CStringArray, CObArray, etc. not the CArray template.

              N 1 Reply Last reply
              0
              • C CPallini

                That is an issue, but it is also, I think, a bad design of the class hierarchy. :)

                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.

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

                This actually happened in one of our applications. We have a lot of code that has been ported and refactored from C to C++. So some of the classes we now have, were once C structs. In one case the myType member was duplicated. This is how I came across this little problem.

                C 1 Reply Last reply
                0
                • B bolivar123

                  This actually happened in one of our applications. We have a lot of code that has been ported and refactored from C to C++. So some of the classes we now have, were once C structs. In one case the myType member was duplicated. This is how I came across this little problem.

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

                  So you have to take into account a little re-design step in your refactoring process... :)

                  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.

                  1 Reply Last reply
                  0
                  • B bolivar123

                    Previous versions of MFC had a CArray class and different variants CStringArray, CObArray, etc. not the CArray template.

                    N Offline
                    N Offline
                    Nemanja Trifunovic
                    wrote on last edited by
                    #10

                    bolivar123 wrote:

                    Previous versions of MFC had a CArray class and different variants CStringArray, CObArray, etc. not the CArray template.

                    Even so, MFC collection classes are considered deprecated within MS VC++ team. See this thread[^]: The MFC collection classes are only there for backwards compatibility. C++ has a standard for collection classes and that is the Standards C++ Library. There is no technical drawback for using any of the standard library in an MFC application. We do not plan on making significant changes in this area. Ronald Laeremans Acting Product Unit Manager Vsual C++ Team


                    Programming Blog utf8-cpp

                    B 1 Reply Last reply
                    0
                    • N Nemanja Trifunovic

                      bolivar123 wrote:

                      Previous versions of MFC had a CArray class and different variants CStringArray, CObArray, etc. not the CArray template.

                      Even so, MFC collection classes are considered deprecated within MS VC++ team. See this thread[^]: The MFC collection classes are only there for backwards compatibility. C++ has a standard for collection classes and that is the Standards C++ Library. There is no technical drawback for using any of the standard library in an MFC application. We do not plan on making significant changes in this area. Ronald Laeremans Acting Product Unit Manager Vsual C++ Team


                      Programming Blog utf8-cpp

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

                      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 1 Reply Last reply
                      0
                      • 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.

                        Z Offline
                        Z Offline
                        Zac Howland
                        wrote on last edited by
                        #12

                        jhwurmbach wrote:

                        Out of dire need when the MS-C++ was so fundamentally broken as being incapable of compiling any STL.

                        It was created because there was no STL at the time. STL wasn't standard until 1999, MFC's collection classes have been around since 1994.

                        jhwurmbach wrote:

                        There is no need to use the afxtempl.h-collections in new software!

                        There is nothing fundamentally wrong with MFC's collection classes. They are perfectly fine, and unless you are actually making use of some of the more advanced features of STL, MFC's templates are even easier to use in some cases. You use the tool that fits you best for what you need to accomplish. To the OP, the biggest problem with the code is the member variables in the derived classes hiding the one in the base class. A better way to do this kind of thing is:

                        class A
                        {
                        public:
                        	A(int type) : _Type(type) {}
                        	virtual ~A() {}
                        
                        	virtual int getType() = 0;
                        };
                        
                        class B : public A
                        {
                        public:
                        	B() {}
                        	virtual ~B() {}
                        
                        	virtual int getType() { return TYPEB; }
                        };
                        
                        class C : public A
                        {
                        public:
                        	C() {}
                        	virtual ~C() {}
                        
                        	virtual int getType() { return TYPEC; }
                        };
                        

                        If you decide to become a software engineer, you are signing up to have a 1/2" piece of silicon tell you exactly how stupid you really are for 8 hours a day, 5 days a week Zac

                        1 Reply Last reply
                        0
                        • 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
                                          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