factory pattern

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
 class Invoice
  8 {
  9 public:
 10         virtual void print() = 0;
 11         Invoice(){cout<<"invoice constructor"<<endl;}
 12         virtual ~Invoice(){cout<<"invoice destructor"<<endl;}
 13 };
 14 
 15 class derived1:public Invoice
 16 {
 17 public:
 18         void print(){cout<<"hello derived1"<<endl;}
 19 };
 20 class derived2:public Invoice
 21 {
 22 public:
 23         void print(){cout<<"hello derived2"<<endl;}
 24 };
 25 
 26 class factory
 27 {
 28 private:
 29         static Invoice* ptr;
 30 public:
 31         factory(){cout<<"factory constructor"<<endl;}
 32         ~factory(){cout<<"factory destructor"<<endl;}
 33         static Invoice* getPtr(int);
 34 
 35 };
 36 
 37 Invoice* factory::ptr = NULL;
 38 
 39 Invoice* factory::getPtr(int type)
 40 {
 41         enum {smooth,rough};
 42         if(type == smooth)
 43         {
 44                 ptr = new derived1;
 45         }
 46         else if(type == rough)
 47         {
 48                 ptr = new derived2;
 49         }
 50         else
 51         {
 52                 return NULL;
 53         }
 54         return ptr;
 55 }
 56 
 57 int main()
 58 {
 59         Invoice *q;
 60         auto_ptr<Invoice> p(factory::getPtr(0));
 61         //if(p)
 62                 p->print();
 63         q = factory::getPtr(1);
 64         if(q)
 65                 q->print();
 66         
 67         return 0;
 68 }       


I know this has a lot of memory leaks, but i was wondering how to delete the object since I cant do it in Invoice and the auto_ptr does not call the factory detructor.
Last edited on
If your destructor is virtual, std::auto_ptr should call the correct one. You might not be able to tell as is because you don't have a destructor defined that does anything (the default for that class will do nothing, then call the base destructor).
Exactly , but how do i delete memory in the base when it has no pointer to the new object
What do you mean?
C++ doesn't keep track of, if an object has a pointer (or reference.) It only keeps track of a variable's scope. Although the pointers go out of scope, the new objects they are pointing to are in memory until you call delete.
You need to call delete on p or q to deallocate the memory (and which will first call their respective deconstructors)

The "leaked" memory will be deallocated (hopefully) by the OS when the program terminates, but no deconstructors will be called.

I hope that helps answer you question jackel7777. I'm not exactly sure what you ment by
... delete memory in the base ...
Last edited on
i cant call delete on p and q in the main() as i dont want the client code to have the responsibility of doing this. I want tit such a way that it automatically deletes.

Hence, with respect to that how would i free that memory in Invoice destructor. The code to be written in destructor that would do this. I cant delete ptr as this will cause a problem if q is still needed. Thats what i meant. Thanks
Last edited on
WHAT?!!! (o_0)
So you're saying you want to "delete the instance of Invoice (ptr), in the Invoice's destructor." In other words, "delete the Invoice when deleting the Invoice..." Do you see the problem yet!

Maybe you worded your question wrong... Deleting the Invoice *ptr will cause you to invoke its destructor. It's already being deleted at that point.

You have a static method factory::getPtr, that makes the Invoice. If you don't want the client to call delete you need to make a static method like factory::doneWithPtr that deletes it. Also you should call delete ptr; to delete the instance created by the last call to factory::getPtr before creating a new instance and storing over the old pointer, and 'leaking' the memory. This also means they only need to call to factory::doneWithPtr once at the end of the code segment. I don't think this is what you want, but it's one solution for this example.

Last edited on
I guess ill re-phrase it. I know that if i do delete in the static pointer, its a recursive call in the destructor. I am saying now 2 new objects have been created, and how do i delete the objects.

I know one has a smart pointer and would call the Invoice destructor, so how should I delete the object at that point. And the other is a simple pointer q. how do i delete that after i used it.
one way is to call delete p; after p is used then delete q after q is used in main().

But this means the client must be careful, but i do not want to give the client the responsibility and i guess thats a better way..so how else can i delete the 2 objects derived1 and derived 2 pointed by p and q.
Last edited on
Anybody??? how do i delete p and q outside main:
Wait... wasn't this solved in another thread by using auto_ptr?

http://www.cplusplus.com/forum/general/40357/
Yes but that was using auto_ptr. Im clear abt that but If i didnt use auto_ptr at all. Just simple pointers, how do i do a clean up not in the client code but myself, like in class Invoice.

Since p,q are not defined in Invoice class but in the client code, so how can i make sure the new objects created are cleaned without depending on the client to be responsible.
See my other response:

You could have your factory class store a list of the pointers it has given out and delete them all at the end of it's lifetime.
@ firedraco
i guess that will be the solution i will use.

just one more:

1
2
3
4
5
6
7
8
9
10
11
12
Invoice *p = factory::getPtr(0);
 62         if(p)
 63                 p->print();
 64         delete p;
 65         
              Invoice *q = factory::getPtr(1);
 66         if(q)
 67                 q->print();
 68         
              p->print();//why is this printing value when this has been deleted. Its printing q's value.
 69         delete q;
 70         return 0
;


note: the factory::getptr() return a static pointer to a new object
That's because your compiler is reusing the memory that p used to use before it got deleted. FYI, trying to use a pointer after it has been deleted is undefined, it could do anything.
The problem here is that you are returning the pointers from a static function. A static function has no concept of "lifetime."
Last edited on
jackel7777 wrote:

Since p,q are not defined in Invoice class but in the client code, so how can i make sure the new objects created are cleaned without depending on the client to be responsible.


You can't.

C++ doesn't work like that.

If you are going to use raw pointers then you have to be responsible for them. The C++ way to make that easier is using smart pointers like std::auto_ptr.

firedraco mentioned a solution by storing a copy of every pointer your factory gives out. However you, the client, are still responsible for deciding when to delete the factory.

Of course you can place the factory in a std::auto_ptr if you like ;o)
Last edited on
Topic archived. No new replies allowed.