請教TStringList與TList的使用時機?又*,&的正確用法為何 |
答題得分者是:axsoft
|
danielj
初階會員 發表:65 回覆:135 積分:40 註冊:2003-06-11 發送簡訊給我 |
|
axsoft
版主 發表:681 回覆:1056 積分:969 註冊:2002-03-13 發送簡訊給我 |
參考這篇文章試試
TList vs. TStringListclass TWorld{ public:TWorld::TWorld(); TWorld::~TWorld(); TStringList* Plants; TStringList* Animals; TList* Oceans; TList* Islands; };Yes, I know there's more than that in a typical world, but that's up to you. First you will need to instantiate your lists in your TWorld constructor, something like: TWorld::TWorld() { Plants = new TStringList; Animals = new TStringList; Oceans = new TList; Islands = new TList; } ;OK, so why did I use a TStringList for plants and animals, and TList for oceans and islands? Well, as you should already know, a TStringList maintains a string plus a pointer to an object for each record in it's list, as opposed to just a pointer to an object only. So when I want to use an object in the plants list, I can use it's string variable to denote which type of class the associated object points to. For example, it is assumed that you will have many types of plants in your world, and not just trees. You may have a TFlower class, and a TTree class, among others. Therefore when you add a flower to the Plants list, you should do it like this: TFlower* Flower = new TFlower; Plants->Add("Flower", (TObject*) Flower); And add trees like this: TTree* Tree = new TTree; Plants->Add("Tree", (TObject*) Tree);So long as you cast your class as a TObject* you can add anything you like to a TStringList. When you need access to a plant object you simply recast as such: TFlower* Flower = NULL; TTree* Tree = NULL; for(int i=0 i < Plants->Count; i ){ if(Plants->Strings == "Flower"){ Flower = (TFlower*) Plants->Objects[i]; ...do something with a flower... } else if(Plants->Strings[i] == "Tree"){ Tree = (TTree*) Plants->Objects[i]; ....do something with a tree... } }Of course, this can get a bit sloppy, so the preferred alternative is to use integers to identify which type of class is stored. You do this by setting up a header file with #define statements.... #ifndef mydefsH #define mydefsH //PLANT TYPES #define ptFLOWER 0 #define ptTREE 1 (etc) //ANIMAL TYPES #define atBEAR 0 #define atFOX 1 (etc) #endif Now when you add something to the plants list, you do it like this: TFlower* Flower = new TFlower; Plants->Add(ptFLOWER, (TObject*) Flower); And when you need something from the plants list, you can do it like this: int iType; for(int i=0; i < Plants->Count; i ){ iType = Plants->Strings[i].ToInt(); switch(iType){ case ptFLOWER: CallFlowerFunc((TFlower*) Plants->Objects[i]; break; case ptTREE: CallTreeFunc((TTree*) Plants->Objects[i]; break; } }So then why do I need a TList* ? Well, for starters, why allocate a bunch of memory to a list of strings if you're not going to use them? TList is nice when you're maintaining a list of objects that are of the same class. Since, for the sake of my example, an ocean is an ocean, and will never be anything else, we could add oceans like this: TOcean* Ocean = new TOcean(); Oceans->Add(Ocean);Notice I don't have to cast my class as a TObject* when using a TList. A tiny bonus I suppose. Also, when I want to do something with my Oceans, it's simply just a matter of iteration: TOcean* O = NULL; for(int i=0; i < Oceans->Count i ){O = (TOcean*) Oceans->Items[i]; O->DoSomething(); }Notice the the object list is now referred to as "Items". To me the biggest benefit of TList is the "Remove()" method. If you have a pointer to the object you want to take out of the oceans list, you very simply call the remove method with the pointer to the object: Oceans->Remove(O); delete O;This will release all memory associated with the object reference in the list, and adjust the lists Capacity and Count values. To do the same with a TStringList, you must use the "Delete()" method, which means that you'll have obtain an integer index for the objects position in the list, by doing something like: int ndx = Plants->IndexOfObject((TObject*) Tree); if(ndx != -1){ Plants->Delete(ndx); Plants->Capacity = Plants->Count; delete Tree; }Notice that the Capacity had to be manually adjusted afterward, another disadvantage of TStringList vs. TList. If you're now getting ready to argue that in most cases you'd be trying to remove something from a list using an integer index as opposed to a pointer to the object, remember that TList also has the Delete() method, same as the TStringList, but TStringList does not have a Remove() method like the TList. You can maintain a TList of various Plant classes by having your TFlower class and TTree class inherit all the TPlant class data members, and thereby maintaining a PlantType integer as part of the TPlant Class, therefore coding your queries like this: TPlant* P = NULL; TFlower* F = NULL; TTree* T = NULL; for(int i=0; i < Plants->Count; i ){ P = (TPlant*) Plants->Items[i]; switch(P->PlantType){ case ptFLOWER: CallFlowerFunc((TFlower*) P); break; case ptTREE: CallTreeFunc((TTree*) P); break; } }Of course if you were going to employ this method, I would set up global variables, one for each type of plant, to avoid having to declare a bunch of pointers at the start of each function "just in case" they get used. When destroying a TList or TStringList, you must use the delete operator in combination with a casting call if you want the appropriate destructor for that class to be called as well: for(int i=0; i < Oceans->Count; i ) { delete (TOcean*) Oceans->Items[i]; } Oceans->Clear(); delete Oceans;Because TOcean might have it's own list of dynamically allocated objects as one of its data members (ie a TList or TStringlist of fish ) it will need to clear these lists and release any memory associated with them, which we would have also had to code in it's destructor method, therefore we must cast as TOcean when deleting, otherwise it will be deleted as though it were a pointer to type void*. If this confuses you then just always use a pointer to an associated class object as shown below: TOcean* O = NULL; for(int i=0; i < Oceans->Count; i ) { O = (TOcean*) Oceans->Items[i]; delete O; } O = NULL; Oceans->Clear(); delete Oceans;Well, that's it! Hope I didn't bore you too much, and now think about what wonderful list maintenance functions you can write in your apps be it a phone book or a video game. Snakebyte snakebyte@bytamin-c.com www.logsim.co.uk [i]HAVE A NICE DAY FOR YOU 發表人 - axsoft 於 2003/07/25 09:53:07 |
danielj
初階會員 發表:65 回覆:135 積分:40 註冊:2003-06-11 發送簡訊給我 |
本站聲明 |
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。 2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。 3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇! |