Singleton with polymorphic classes
-
// 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
-
// 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
-
There is a reason that Singleton is a Software Design Pattern ;)
"No matter where you go, there your are." - Buckaroo Banzai
-pete
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.
-
// 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
Make the derived constructors
private
(orprotected
), 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"
-
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.
-
Make the derived constructors
private
(orprotected
), 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"