在一雨田的Blog有一篇关于Flyweight模式的文章: http://blog.csdn.net/dylgsy/archive/2006/08/10/1045678.aspx
但在编译运行时,问题产生了:出版社和作者显示不了。
一雨田原来的代码:
- // Flyweight.cpp
- #pragma warning(disable: 4786)
- #include <iostream>
- #include <map>
- #include <string>
- #include <stdlib.h>
- using namespace std;
- class Book
- {
- public:
- string GetPublish() {return *m_publishCompany;}
- string GetWriter() {return *m_writer;}
- int GetBookID() {return m_bookID;}
- int GetPrice() {return m_price;}
- string GetName() {return m_name;}
- void SetPublish(string *s) {m_publishCompany = s;}
- void SetWriter(string *s) {m_writer = s;}
- void SetBookID(int id) {m_bookID = id;}
- void SetPrice(int price) {m_price = price;}
- void SetName(string &s) {m_name = s;}
- private:
- string *m_publishCompany; // 出版社
- string *m_writer; // 作者
- int m_bookID; // 书籍编号
- int m_price; // 价钱
- string m_name; // 书名
- };
- class PublishFlyweight
- {
- public:
- PublishFlyweight(string s)
- {
- m_name = s;
- }
- string GetName()
- {
- return m_name;
- }
- private:
- string m_name;
- };
- class PublishFlyweightFactory
- {
- public:
- PublishFlyweight* GetPublish(string key)
- {
- PublishFlyweight *p;
- map<string, PublishFlyweight*>::iterator it;
- it = mapPublish.find(key);
- // 存在这个出版社
- if(it != mapPublish.end() )
- {
- // 这里可能有点难懂,请查阅STL的帮助文档
- // 其实second就是指 map<string, PublishFlyweight*> 的 PublishFlyweight*
- p = (*it).second;
- cout << "已经有这个出版社: " << p->GetName() << " 你节省了" << strlen(p->GetName().c_str()) << "字节的空间" << endl;
- }
- else
- {// 插入这个PublishFlyweight
- p = new PublishFlyweight(key);
- mapPublish[key] = p;
- }
- return p;
- }
- private:
- map<string, PublishFlyweight*> mapPublish;
- };
- class WriterFlyweight
- {
- public:
- WriterFlyweight(string s)
- {
- m_name = s;
- }
- string GetName()
- {
- return m_name;
- }
- private:
- string m_name;
- };
- class WriterFlyweightFactory
- {
- public:
- WriterFlyweight* GetWriter(string key)
- {
- WriterFlyweight *p;
- map<string, WriterFlyweight*>::iterator it;
- it = mapWriter.find(key);
- // 存在这个Writer
- if(it != mapWriter.end() )
- {
- // 这里可能有点难懂,请查阅STL的帮助文档
- // 其实second就是指 map<string, WriterFlyweight*> 的 WriterFlyweight*
- p = (*it).second;
- cout << "已经有这个作者名字: " << p->GetName() << " 你节省了" << strlen(p->GetName().c_str()) << "字节的空间" << endl;
- }
- else
- {// 插入这个PublishFlyweight
- p = new WriterFlyweight(key);
- mapWriter[key] = p;
- }
- return p;
- }
- private:
- map<string, WriterFlyweight*> mapWriter;
- };
- void ShowBookInfo(Book book)
- {
- cout << "书名:" << book.GetName() << endl;
- cout << "编号:" << book.GetBookID() << endl;
- cout << "价钱:" << book.GetPrice() << endl;
- cout << "出版:" << book.GetPublish() << endl;
- cout << "作者:" << book.GetWriter() << endl;
- cout << endl;
- }
- void main()
- {
- PublishFlyweightFactory pff;
- WriterFlyweightFactory wff;
- Book book1, book2, book3;
- book1.SetPublish( &(pff.GetPublish("机械工业出版社")->GetName()) );
- book1.SetWriter( &(wff.GetWriter("候捷")->GetName()) );
- book1.SetBookID(0000);
- book1.SetPrice(20);
- book1.SetName(string("<<C++好野>>"));
- ShowBookInfo(book1);
- book2.SetPublish( &(pff.GetPublish("人民邮电出版社")->GetName()) );
- book2.SetWriter( &(wff.GetWriter("候捷")->GetName()) );
- book2.SetBookID(0001);
- book2.SetPrice(30);
- book2.SetName(string("<<C++是好劲>>"));
- ShowBookInfo(book2);
- book3.SetPublish( &(pff.GetPublish("机械工业出版社")->GetName()) );
- book3.SetWriter( &(wff.GetWriter("一雨田")->GetName()) );
- book3.SetBookID(0002);
- book3.SetPrice(50);
- book3.SetName(string("<<C++无得顶,我是铁头功...>>"));
- ShowBookInfo(book3);
- system("pause");
- }
是什么原因呢?仔细分析其源代码,发现“book1.SetPublish( &(pff.GetPublish("机械工业出版社")->GetName()) );”这一行使用了临时变量,在取“pff.GetPublish("机械工业出版社")->GetName() ”返回一个临时变量,而再取临时变量的地址&,运行到下一行时,这个临时地址将变成一个无效的地址,指向任何值都可以出现。因此,编程中是严禁这样使用的,编程时都应注意此类问题。修改好的代码如下:
- /*
- 来源:一雨田Blog
- 问题:出版社和作者显示不了
- 修改:qmroom
- */
- // Flyweight.cpp
- #include <iostream>
- #include <map>
- #include <string>
- #include <stdlib.h>
- using namespace std;
- typedef char CHAR;
- typedef CHAR *LPSTR;
- typedef const CHAR *LPCSTR;
- class Book
- {
- public:
- string GetPublish() {return *m_publishCompany;}
- string GetWriter() {return *m_writer;}
- int GetBookID() {return m_bookID;}
- int GetPrice() {return m_price;}
- string GetName() {return m_name;}
- void SetPublish(string *s) {m_publishCompany = s;}
- void SetWriter(string *s) {m_writer = s;}
- void SetBookID(int id) {m_bookID = id;}
- void SetPrice(int price) {m_price = price;}
- void SetName(LPCSTR s) {m_name = s;}
- private:
- string *m_publishCompany; // 出版社
- string *m_writer; // 作者
- int m_bookID; // 书籍编号
- int m_price; // 价钱
- string m_name; // 书名
- };
- class PublishFlyweight
- {
- public:
- PublishFlyweight(string s)
- {
- m_name = new string(s);
- }
- virtual ~PublishFlyweight()
- {
- delete(m_name);
- }
- string *GetName()
- {
- return m_name;
- }
- private:
- string *m_name;
- };
- class PublishFlyweightFactory
- {
- public:
- PublishFlyweight* GetPublish(string key)
- {
- PublishFlyweight *p;
- map<string, PublishFlyweight*>::iterator it;
- it = mapPublish.find(key);
- // 存在这个出版社
- if(it != mapPublish.end() )
- {
- // 这里可能有点难懂,请查阅STL的帮助文档
- // 其实second就是指 map<string, PublishFlyweight*> 的 PublishFlyweight*
- p = (*it).second;
- cout << "已经有这个出版社: " << *(p->GetName()) << " 你节省了" << strlen((*(p->GetName())).c_str()) << "字节的空间" << endl;
- }
- else
- {
- // 插入这个PublishFlyweight
- p = new PublishFlyweight(key);
- mapPublish[key] = p;
- }
- return p;
- }
- private:
- map<string, PublishFlyweight*> mapPublish;
- };
- class WriterFlyweight
- {
- public:
- WriterFlyweight(string s)
- {
- m_name = new string(s);
- }
- virtual ~WriterFlyweight()
- {
- delete(m_name);
- }
- string *GetName()
- {
- return m_name;
- }
- private:
- string *m_name;
- };
- class WriterFlyweightFactory
- {
- public:
- WriterFlyweight* GetWriter(string key)
- {
- WriterFlyweight *p;
- map<string, WriterFlyweight*>::iterator it;
- it = mapWriter.find(key);
- // 存在这个Writer
- if(it != mapWriter.end() )
- {
- // 这里可能有点难懂,请查阅STL的帮助文档
- // 其实second就是指 map<string, WriterFlyweight*> 的 WriterFlyweight*
- p = (*it).second;
- cout << "已经有这个作者名字: " << *(p->GetName()) << " 你节省了" << strlen((*(p->GetName())).c_str()) << "字节的空间" << endl;
- }
- else
- {
- // 插入这个PublishFlyweight
- p = new WriterFlyweight(key);
- mapWriter[key] = p;
- }
- return p;
- }
- private:
- map<string, WriterFlyweight*> mapWriter;
- };
- void ShowBookInfo(Book book)
- {
- cout << "书名:" << book.GetName() << endl;
- cout << "编号:" << book.GetBookID() << endl;
- cout << "价钱:" << book.GetPrice() << endl;
- cout << "出版:" << book.GetPublish() << endl;
- cout << "作者:" << book.GetWriter() << endl;
- cout << endl;
- }
- void main()
- {
- PublishFlyweightFactory pff;
- WriterFlyweightFactory wff;
- Book book1, book2, book3;
- book1.SetPublish( pff.GetPublish("机械工业出版社")->GetName() );
- book1.SetWriter( wff.GetWriter("qmroom")->GetName() );
- book1.SetBookID(0000);
- book1.SetPrice(20);
- book1.SetName(("<<C++好野>>"));
- ShowBookInfo(book1);
- book2.SetPublish( pff.GetPublish("人民邮电出版社")->GetName() );
- book2.SetWriter( wff.GetWriter("qmroom")->GetName() );
- book2.SetBookID(0001);
- book2.SetPrice(30);
- book2.SetName(("<<C++是好劲>>"));
- ShowBookInfo(book2);
- book3.SetPublish( pff.GetPublish("机械工业出版社")->GetName() );
- book3.SetWriter( wff.GetWriter("一雨田")->GetName() );
- book3.SetBookID(0002);
- book3.SetPrice(50);
- book3.SetName(("<<C++无得顶,我是铁头功...>>"));
- ShowBookInfo(book3);
- system("pause");
- }
其实,这段代码还有很多可以修改的地方,以便提高性能和便于维护和使用。请看设计模式简单代码之Flyweight模式(二)。