11.測試智能指針
//TestMySmartPointer.h #pragma once #if defined(_MSC_VER) #pragma warning ( disable : 4786 ) #endif #include "MySmartPointer.h" #include <iostream> #include <cstdlib> //測試類基類,測試智能指針:MySmartPointer class MyTestObject { public: typedef MyTestObject Self; typedef MySmartPointer<MyTestObject> Pointer; typedef MySmartPointer<const MyTestObject> ConstPointer; //創建對象 static MyTestObject::Pointer New(); //增加/減少 引用計數 virtual void Register() { std::cout << "Register " << *this << " count:" << (m_ReferenceCount+1) << " " << std::endl; m_ReferenceCount++; } virtual void UnRegister() { std::cout << "UnRegister " << this << " count:" << (m_ReferenceCount-1) << " " << std::endl; m_ReferenceCount--; if ( m_ReferenceCount == 0 ) { delete this; } } //operator << inline friend std::ostream &operator << ( std::ostream &os, MyTestObject const& o) { os << "MyTestObject " << (void const * )&o << " " << o.m_ReferenceCount; return os; } protected: MyTestObject() { m_ReferenceCount = 0; // cout << *this 會調用上面重載的友員函數 std::cout << "MyTestObject(): " << *this << std::endl; } virtual ~MyTestObject() { std::cout << "~MyTestObject(): " << *this << std::endl; } private: unsigned int m_ReferenceCount; }; // MyTestObject::Pointer MyTestObject::New() { return MyTestObject::Pointer(new MyTestObject); } //測試子類, 繼承自 MyTestObject class MyTestObjectSubClass : public MyTestObject { public: typedef MyTestObjectSubClass Self; typedef MyTestObject Superclass; typedef MySmartPointer<MyTestObjectSubClass> Pointer; typedef MySmartPointer<const MyTestObjectSubClass> ConstPointer; // static Pointer New(); }; // MyTestObjectSubClass::Pointer MyTestObjectSubClass::New() { return MyTestObjectSubClass::Pointer(new MyTestObjectSubClass); } //測試向上類型轉換,其參數爲基類智能指針 void TestUpCastPointer(MyTestObject::Pointer) { std::cout << "TestUpCastPointer()... " << std::endl; } //測試向上類型轉換,其參數爲基類原始指針 void TestUpCast(MyTestObject*) { std::cout << "TestUpCast()... " << std::endl; } //測試向上類型轉換,其參數爲基類原始指針 void TestCopyConstruct(MySmartPointer<MyTestObject> s) { std::cout << "TestCopyConstruct()... " << std::endl; } //用於測試的函數 int MySmartPointerTest(int argc, char* argv[] ) { std::cout << "Test MySmartPointer start:/n" << std::endl; //新建一個基類指針,指向一個具體的子類對象 MyTestObject::Pointer to(MyTestObjectSubClass::New()); //1.創建子類指針,構造,+1; 2.有參構造 to, +1; 3.離開作用範圍,析構, -1; count=1; std::cout << "-------------------------------------------1" << std::endl; //測試安全向下類型轉換 //使用 dynamic_cast 將上面的指向子類對象的基類指針轉換爲子類指針 MyTestObjectSubClass::Pointer sc = dynamic_cast<MyTestObjectSubClass*>(to.GetPointer()); //1.構造 sc, count=2; std::cout << "-------------------------------------------2" << std::endl; //測試向上轉換類型,該函數接收一個基類原始指針 TestUpCast(sc); //1.向上類型轉換,什麼都沒做. std::cout << "-------------------------------------------3" << std::endl; //測試向上轉換類型,該函數接收一個基類智能指針 TestUpCastPointer(sc.GetPointer()); //1.該函數參數爲 MyTestObject::Pointer,先調用構造一個指向基類的指針, count=3; //2.離開該函數作用域後, 析構, count=2; std::cout << "-------------------------------------------4" << std::endl; //This will not work, but only in construction //itkTestObject::Pointer p = sc; // For construction use the constructor call: // Test casting up the tree, note no explict cast is required MyTestObject::Pointer p(sc); //1.有參構造, +1, to=3; std::cout << "-------------------------------------------5" << std::endl; // No cast is required for assignment p = sc; //1.調用 operator=,先減少左邊引用計數,再增加右邊引用計數,持平. count=3; std::cout << "-------------------------------------------6" << std::endl; std::cout <<"second test" << std::endl; { MyTestObject::Pointer o1 = MyTestObject::New(); std::cout << "o1 " << &o1 << std::endl; MyTestObject::Pointer o2 = MyTestObject::New(); std::cout << "o2 " << &o2 << std::endl; MyTestObject::Pointer o3 = MyTestObject::New(); std::cout << "o3 " << &o3 << std::endl; MyTestObject::Pointer o4 = MyTestObject::New(); std::cout << "o4 " << &o4 << std::endl; std::cout << "-------------------------------------------7" << std::endl; o1 = o2; //1.o1 引用計數減 1, 析構. 2. o2 引用計數加 1, = 2; std::cout << "---------------8" << std::endl; o2 = o3; //1.o2 引用計數減 1, =1; 2. o3 引用計數加 1, = 2; std::cout << "---------------9" << std::endl; o4 = o1; //1.o4 引用計數減 1, 析構. 2. o1, 即 o2 引用計數加 1, = 2; std::cout << "---------------10" << std::endl; //至此,o1=0, o2=2, o3=2; o4=0; //1. o4 析構, 即 o2 減 1; 2. o3 析構, 即 o3 減 1; //3. o2 析構, 即 o3 減 1; o3 指向的對象最終析構. //4. o1 析構, 即 o3 析構; o2 指向的對象最終析構. } std::cout <<"end second test" << std::endl << std::endl; std::cout <<"first test" << std::endl; { MyTestObject::Pointer o1 = MyTestObject::New(); //1. 構造 MyTestObject; 2. 構造其智能指針; //3. 智能指針離開作用域,析構,引用計數減 1, 爲 0; //4. 其指向的對象析構. } std::cout <<"end first test" << std::endl << std::endl; //看拷貝構造函數 { MyTestObject::Pointer o1 = MyTestObject::New(); std::cout << "------------------------11" << std::endl; MyTestObject::Pointer o2; //默認構造函數 std::cout << "------------------------12" << std::endl; TestCopyConstruct(o1); //該函數的參數爲一個對象, 向函數按值傳遞參數, 會調用拷貝構造函數 std::cout << "------------------------13" << std::endl; } std::cout << std::endl; //1.最後,剛開始創建的對象引用計數 從 3 減少至 0, 然後析構. return EXIT_SUCCESS; }
12.測試對象工廠
//TestMyObjectFactory.h #pragma once #if defined(_MSC_VER) #pragma warning ( disable : 4786 ) #endif #include "MyObjectFactory.h" #include <string> #include <list> //測試對象工廠: //1.對象工廠可以在運行時進行動態替換 //2.我們從 MyObject 繼承得到兩個版本的類: TestObject1, TestObject2 //然後創建一個創建該類對象的對象工廠, 並在開始時設置創建版本 TestObject1 //運行時, 通過設置 m_EnabledFlag變量, 可以將其動態替換爲版本 TestObject2 // //版本1 class TestObject1 : public MyObject { public: typedef TestObject1 Self; typedef MyObject Superclass; typedef MySmartPointer<Self> Pointer; typedef MySmartPointer<const Self> ConstPointer; //通過對象工廠創建對象實例,返回指向對象實例的智能指針 MyNewMacro(Self); //virtual const char *GetNameOfClass() const; MyTypeMacro(TestObject1, MyObject); // virtual ~TestObject1() { } TestObject1(){ } private: TestObject1(const Self&); void operator=(const Self&); }; //版本2 class TestObject2 : public MyObject { public: typedef TestObject2 Self; typedef MyObject Superclass; typedef MySmartPointer<Self> Pointer; typedef MySmartPointer<const Self> ConstPointer; //通過對象工廠創建對象實例,返回指向對象實例的智能指針 MyNewMacro(Self); //virtual const char *GetNameOfClass() const; MyTypeMacro(TestObject2, MyObject); // virtual ~TestObject2() { } TestObject2(){ } private: TestObject2(const Self&); void operator=(const Self&); }; //用於創建 TestObject1, TestObject2 的對象工廠. class TestFactory : public MyObjectFactoryBase { public: typedef TestFactory Self; typedef MyObjectFactoryBase Superclass; typedef MySmartPointer<Self> Pointer; typedef MySmartPointer<const Self> ConstPointer; //描述該對象工廠... const char* GetDescription() const { return "A Test Factory"; } //使用 new 操作符實例化對象工廠 MyFactorylessNewMacro(Self); MyTypeMacro(TestFactory, MyObjectFactoryBase); //註冊該對象工廠. static void RegisterOneFactory(void) { TestFactory::Pointer factory = TestFactory::New(); //調用對象工廠基類的靜態方法 MyObjectFactoryBase::RegisterFactory(factory); } private: TestFactory(const Self&); void operator=(const Self&); //構造函數 //註冊其能創建的對象,及其版本信息與描述 TestFactory() { //TestFactory 可以創建兩種對象: TestObject1, TestObject2; this->RegisterOverride( typeid(MyObject).name(), //父類 typeid(TestObject1).name(), //自己 "Test Object factory override 1", //對工廠的描述 true, //true, 默認創建該版本 MyCreateObjectFunction< TestObject1 >::New() ); //用於創建該對象的回調函數 this->RegisterOverride( typeid(MyObject).name(), typeid(TestObject2).name(), "Test Object factory override 2", false, //false, 不創建該版本 MyCreateObjectFunction< TestObject2 >::New()); } }; //測試指針 v 所指的對象是否是 expectedClassName 類的對象實例. typedef MyObject::Pointer myPointer; bool TestNewObject(myPointer v, const char* expectedClassName) { std::cout << "v->GetNameOfClass(): " << v->GetNameOfClass(); std::cout << ", expectedClassName: " << expectedClassName << std::endl; if(strcmp(v->GetNameOfClass(), expectedClassName) != 0) { std::cout << "Test Failed" << std::endl; return false; } return true; } //測試對象工廠 int MyObjectFactoryTest(int argc, char* argv[]) { TestFactory::Pointer factory = TestFactory::New(); MyObjectFactoryBase::RegisterFactory(factory); //列出所有已經註冊的對象工廠 std::list<MyObjectFactoryBase *> factories = MyObjectFactoryBase::GetRegisteredFactories(); //打印已經註冊的對象工廠的信息 //依次打印對象工廠鏈表上的各個對象工廠的信息, 當然這裏只註冊了一個對象工廠 std::cout << "-------- Registered factories --------" << std::endl; for ( std::list<MyObjectFactoryBase*>::iterator f = factories.begin(); f != factories.end(); ++f ) { std::cout << " Factory description: " << (*f)->GetDescription() << std::endl; std::list<std::string> overrides = (*f)->GetClassOverrideNames(); std::list<std::string> names = (*f)->GetClassOverrideWithNames(); std::list<bool> enableflags = (*f)->GetEnableFlags(); std::list<std::string> descriptions = (*f)->GetClassOverrideDescriptions(); std::list<std::string>::const_iterator n = names.begin(); std::list<std::string>::const_iterator d = descriptions.begin(); std::list<bool>::const_iterator e = enableflags.begin(); //每個對象工廠可能能夠創建同一對象的多種不同版本, 分別打印 for ( std::list<std::string>::const_iterator o = overrides.begin(); o != overrides.end(); ++o, ++n, ++d, ++e) { std::cout << " Override " << *o << " with " << *n << std::endl << " described as /"" << *d << "/"" << std::endl << " enabled " << *e << std::endl; } } std::cout << "----------- -----------" << std::endl; //*/ //Tets1: 測試是否能夠創建版本 TestObject1 的實例 MyObject::Pointer v = MyObject::New(); int status = EXIT_SUCCESS; if (!TestNewObject(v, "TestObject1")) //Success { status = EXIT_FAILURE; }//*/ std::cout << "-------------------------------------------------------1" << std::endl; //Test2: 關閉 ID 爲 MyObject 的對象工廠, 這時無法創建 TestObject1 與 TestObject2 factory->Disable(typeid(MyObject).name()); v = MyObject::New(); //所以該語句得到的就是 MyObject if (!TestNewObject(v, "MyObject")) { status = EXIT_FAILURE; } std::cout << "-------------------------------------------------------2" << std::endl; //Test3: 打開 ID 爲 MyObject 的對象工廠, 並輸出其相關信息進行驗證 factory->SetEnableFlag(true, typeid(MyObject).name(), typeid(TestObject2).name()); //使其能夠創建版本 TestObject2 std::cout << typeid(MyObject).name() << " overridden by " << typeid(TestObject2).name() << std::endl << " EnableFlag is " << factory->GetEnableFlag(typeid(MyObject).name(), typeid(TestObject2).name()) << std::endl; v = MyObject::New(); if (!TestNewObject(v, "TestObject2")) { status = EXIT_FAILURE; } std::cout << "-------------------------------------------------------3" << std::endl; //Test4: 設置工廠可以創建版本 TestObject1, 不能創建版本 TestObject2 factory->SetEnableFlag(false, typeid(MyObject).name(), typeid(TestObject2).name()); factory->SetEnableFlag(true, typeid(MyObject).name(), typeid(TestObject1).name()); v = MyObject::New(); if (!TestNewObject(v, "TestObject1")) { status = EXIT_FAILURE; } std::cout << "-------------------------------------------------------4" << std::endl; //Test5: 將所有的對象工廠註銷 MyObjectFactoryBase::UnRegisterFactory(factory); v = MyObject::New(); //所以該語句得到的就是 MyObject if (!TestNewObject(v, "MyObject")) { status = EXIT_FAILURE; } std::cout << "-------------------------------------------------------5" << std::endl; //Test6: 註銷對象工廠後, 無法創建版本 TestObject1, TestObject2 v = MyObject::New(); if (!TestNewObject(v, "TestObject1")) //註銷對象工廠後 Test Failed! { status = EXIT_FAILURE; } std::cout << "-------------------------------------------------------6" << std::endl; //Test7: 註冊對象工廠, 恢復到 Test1 的狀態. TestFactory::RegisterOneFactory(); //再次註冊對象工廠 v = MyObject::New(); if (!TestNewObject(v, "TestObject1")) { status = EXIT_FAILURE; } std::cout << "/nTest MyObjectFactory End...." << std::endl; return status; }
13.主驅動
//Test.cpp //分別測試 MySmartPointer 與 MyObjectFactory #include "TestMySmartPointer.h" #include "TestMyObjectFactory.h" int main(int argc, char* argv[]) { //Test MySmartPointer std::cout << "-----------------------Test MySmartPointer-----------------------/n"; MySmartPointerTest(argc, argv); //Test MyObjectFactory std::cout << "/n-----------------------Test MyObjectFactory----------------------/n"; MyObjectFactoryTest(argc, argv); return EXIT_SUCCESS; }