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. Singleton with polymorphic classes

Singleton with polymorphic classes

Scheduled Pinned Locked Moved C / C++ / MFC
c++tutorialquestion
6 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.
  • K Offline
    K Offline
    kylur
    wrote on last edited by
    #1

    // D.cpp: Singleton returning pointer to polymorphic class // // [Q] How to change definitions of derived classes to disallow // direct construction of derived objects? // ie CDerived1 D1 or CDerived2* D2 = new CDerived2 should not // possible! // #include "stdafx.h" #include #include #include using namespace std; /////////////////////////////////////////////////////////////////////////////// static int Type(0); /////////////////////////////////////////////////////////////////// forwards // class CBase; class CDerived1; class CDerived2; /////////////////////////////////////////////////////////////////////////////// class CBase { public: static CBase* GetInstance(); virtual ~CBase(); virtual ostream& Print(ostream& os) const; protected: CBase(); CBase(const CBase&); // not implemented CBase& operator=(const CBase&); // not implemented private: static auto_ptr Instance_; // will auto destroy }; /////////////////////////////////////////////////////////////////////////////// class CDerived1 : public CBase { public: virtual ~CDerived1(); ostream& Print(ostream& os) const; public: // but should be protected to disallow direct creation CDerived1(); CDerived1(const CDerived1&); // not implemented CDerived1& operator=(const CDerived1&); // not implemented }; /////////////////////////////////////////////////////////////////////////////// class CDerived2 : public CBase { public: virtual ~CDerived2(); ostream& Print(ostream& os) const; public: // but should be protected to disallow direct creation CDerived2(); CDerived2(const CDerived2&); // not implemented CDerived2& operator=(const CDerived2&); // not implemented }; /////////////////////////////////////////////////////////////////////////////// ostream& operator<<(ostream& os, const CBase& rhs) { return rhs.Print(os); }; ostream& operator<<(ostream& os, const CDerived1& rhs) { return rhs.Print(os); }; ostream& operator<<(ostream& os, const CDerived2& rhs) { return rhs.Print(os); }; /////////////////////////////////////////////////////////////////////////////// auto_ptr CBase::Instance_; CBase::CBase() { cout << "Base: ctor\n"; } CBase::~CBase() { cout << "Base: dtor\n"; } CBase* CBase::GetInstance() { // as coded is not thread-safe! required double-check/lock // if (Instance_.get() == NULL) { switch (Type) { case 1: Instance_.reset(new CDerived1); break; case 2

    P R 2 Replies Last reply
    0
    • K kylur

      // D.cpp: Singleton returning pointer to polymorphic class // // [Q] How to change definitions of derived classes to disallow // direct construction of derived objects? // ie CDerived1 D1 or CDerived2* D2 = new CDerived2 should not // possible! // #include "stdafx.h" #include #include #include using namespace std; /////////////////////////////////////////////////////////////////////////////// static int Type(0); /////////////////////////////////////////////////////////////////// forwards // class CBase; class CDerived1; class CDerived2; /////////////////////////////////////////////////////////////////////////////// class CBase { public: static CBase* GetInstance(); virtual ~CBase(); virtual ostream& Print(ostream& os) const; protected: CBase(); CBase(const CBase&); // not implemented CBase& operator=(const CBase&); // not implemented private: static auto_ptr Instance_; // will auto destroy }; /////////////////////////////////////////////////////////////////////////////// class CDerived1 : public CBase { public: virtual ~CDerived1(); ostream& Print(ostream& os) const; public: // but should be protected to disallow direct creation CDerived1(); CDerived1(const CDerived1&); // not implemented CDerived1& operator=(const CDerived1&); // not implemented }; /////////////////////////////////////////////////////////////////////////////// class CDerived2 : public CBase { public: virtual ~CDerived2(); ostream& Print(ostream& os) const; public: // but should be protected to disallow direct creation CDerived2(); CDerived2(const CDerived2&); // not implemented CDerived2& operator=(const CDerived2&); // not implemented }; /////////////////////////////////////////////////////////////////////////////// ostream& operator<<(ostream& os, const CBase& rhs) { return rhs.Print(os); }; ostream& operator<<(ostream& os, const CDerived1& rhs) { return rhs.Print(os); }; ostream& operator<<(ostream& os, const CDerived2& rhs) { return rhs.Print(os); }; /////////////////////////////////////////////////////////////////////////////// auto_ptr CBase::Instance_; CBase::CBase() { cout << "Base: ctor\n"; } CBase::~CBase() { cout << "Base: dtor\n"; } CBase* CBase::GetInstance() { // as coded is not thread-safe! required double-check/lock // if (Instance_.get() == NULL) { switch (Type) { case 1: Instance_.reset(new CDerived1); break; case 2

      P Offline
      P Offline
      palbano
      wrote on last edited by
      #2

      There is a reason that Singleton is a Software Design Pattern ;)

      "No matter where you go, there your are." - Buckaroo Banzai

      -pete

      K 1 Reply Last reply
      0
      • P palbano

        There is a reason that Singleton is a Software Design Pattern ;)

        "No matter where you go, there your are." - Buckaroo Banzai

        -pete

        K Offline
        K Offline
        kylur
        wrote on last edited by
        #3

        I appreciate your taking the time to look at this question but your "answer" is less than helpful. The singleton pattern is implemented correctly; I've even implemented the auto_ptr to destroy on exit and noted the need for thread-safety (not required in this simple testbed). I've reread the GoF section on singletons and search >100 sites, lots of info on regular classes but nothing on polymorphic classes. The GoF site shows a polymorphic use but the ctor is public in all the dervied classes, so, they could be directly instantiated. So, again, how to ensure derived classes are not implemented directly.

        P 1 Reply Last reply
        0
        • K kylur

          // D.cpp: Singleton returning pointer to polymorphic class // // [Q] How to change definitions of derived classes to disallow // direct construction of derived objects? // ie CDerived1 D1 or CDerived2* D2 = new CDerived2 should not // possible! // #include "stdafx.h" #include #include #include using namespace std; /////////////////////////////////////////////////////////////////////////////// static int Type(0); /////////////////////////////////////////////////////////////////// forwards // class CBase; class CDerived1; class CDerived2; /////////////////////////////////////////////////////////////////////////////// class CBase { public: static CBase* GetInstance(); virtual ~CBase(); virtual ostream& Print(ostream& os) const; protected: CBase(); CBase(const CBase&); // not implemented CBase& operator=(const CBase&); // not implemented private: static auto_ptr Instance_; // will auto destroy }; /////////////////////////////////////////////////////////////////////////////// class CDerived1 : public CBase { public: virtual ~CDerived1(); ostream& Print(ostream& os) const; public: // but should be protected to disallow direct creation CDerived1(); CDerived1(const CDerived1&); // not implemented CDerived1& operator=(const CDerived1&); // not implemented }; /////////////////////////////////////////////////////////////////////////////// class CDerived2 : public CBase { public: virtual ~CDerived2(); ostream& Print(ostream& os) const; public: // but should be protected to disallow direct creation CDerived2(); CDerived2(const CDerived2&); // not implemented CDerived2& operator=(const CDerived2&); // not implemented }; /////////////////////////////////////////////////////////////////////////////// ostream& operator<<(ostream& os, const CBase& rhs) { return rhs.Print(os); }; ostream& operator<<(ostream& os, const CDerived1& rhs) { return rhs.Print(os); }; ostream& operator<<(ostream& os, const CDerived2& rhs) { return rhs.Print(os); }; /////////////////////////////////////////////////////////////////////////////// auto_ptr CBase::Instance_; CBase::CBase() { cout << "Base: ctor\n"; } CBase::~CBase() { cout << "Base: dtor\n"; } CBase* CBase::GetInstance() { // as coded is not thread-safe! required double-check/lock // if (Instance_.get() == NULL) { switch (Type) { case 1: Instance_.reset(new CDerived1); break; case 2

          R Offline
          R Offline
          Ryan Binns
          wrote on last edited by
          #4

          Make the derived constructors private (or protected), and add "friend CBase;" to your derived class definition.

          Ryan

          "Punctuality is only a virtue for those who aren't smart enough to think of good excuses for being late" John Nichol "Point Of Impact"

          K 1 Reply Last reply
          0
          • K kylur

            I appreciate your taking the time to look at this question but your "answer" is less than helpful. The singleton pattern is implemented correctly; I've even implemented the auto_ptr to destroy on exit and noted the need for thread-safety (not required in this simple testbed). I've reread the GoF section on singletons and search >100 sites, lots of info on regular classes but nothing on polymorphic classes. The GoF site shows a polymorphic use but the ctor is public in all the dervied classes, so, they could be directly instantiated. So, again, how to ensure derived classes are not implemented directly.

            P Offline
            P Offline
            palbano
            wrote on last edited by
            #5

            kylur wrote: your "answer" is less than helpful Yes that is correct. I did not understand the point or goal of your design and actually still don't. Perhaps Mr. Binns solution is what you were looking for. Good luck

            1 Reply Last reply
            0
            • R Ryan Binns

              Make the derived constructors private (or protected), and add "friend CBase;" to your derived class definition.

              Ryan

              "Punctuality is only a virtue for those who aren't smart enough to think of good excuses for being late" John Nichol "Point Of Impact"

              K Offline
              K Offline
              kylur
              wrote on last edited by
              #6

              Much appreciated... exactly what I needed. Thank you, Kylur.

              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