开发者

C++ inheritance designing a linked list

I wanted to make a linked list class ListList that inherits from a class List. ListList uses functions from List, but has its own functions. It has its own start pointer that points to the beginning of the list, and its own Node struct that holds a different amount of elements.

But, it looks like, when one of List's functions are called from ListList, List uses it's own start pointer and Node. But I want ListList's start pointer and Node to be used. Can someone help me figure this out? I could post some code, but I don't know what part would be relevant...

this is the one I called List above

class LinkList
{
public:
LinkList(); //constructor that sets the start pointer to NULL, to show that the list is empty
~LinkList(); //destructor that deletes each node in the linked list
LinkList(const LinkList &original); //copy constructor
void addToken(string token); //creates a node with the given token and places it at the beginning of the linked list
string showList(); //returns a string of tokens, separated by commas and spaces
bool findToken(string token); //searches linked list for the given token, returns true if the token is in the list
string getToken(string word); //searches linked list for a token that begins with the given word.
                              //Returns the full token if there's a token that begins with the given word, else returns an empty string
void deleteList();
protected:

struct Node //each node of the linked list, held together by the next pointer
{
    string token;
    bool second_word; //tells whether or not there is a space within the token (a two-word keyword)
                      //This could be easily changed to an int that tells how many words are within the keyword (for mul开发者_开发百科ti-word keywords)
    Node *next; //pointer to the next node of the linked list. NULL if there is no next node
};

Node *start; //pointer to the beginning of the linked list, and the last added node
bool twoWordToken(string token); //returns true if there is a space located within a token, meaning the token consists of two words.
};

This is the one I called ListList above

class LinkListList: public LinkList
{
public:
LinkListList(); //modified contructor initiates the pointers start and ptrNode
~LinkListList(); //modified destructor deletes all nodes and secondaryList nodes
LinkListList(const LinkListList &original); //copy constructor
bool addSubList(LinkList subList, string commandWord); //calls setPtrNode, then adds the given subList to that node
bool findSubToken(string commandWord, string token); //calls setPtrNode, then calls on that node's secondaryList's findToken function
                                                     //returns true if the findToken function returns true, else returns false
string showSubList(string commandWord); //returns a string of tokens, separated by commas and spaces, representing the subList of the given token
string getSubToken(string word, string commandWord); //searches commandWord's subList for a token that begins with the given word.
                                              //Returns the full token if there's a token that begins with the given word, else returns an empty string
private:

struct Node //each node of the linked list, held together by the next pointer
{
    string token;
    bool second_word; //tells whether or not there is a space within the token (a two-word keyword)
    LinkList secondaryList; //keeps a list of all related words
    Node *next;
};

Node *start; //pointer to the beginning of the linked list
Node *ptrNode; //this pointer is used for the functions
void setPtrNode(string token); //sets ptrNode to point to the node containing the specified token. ptrNode is NULL if the token could not be found  
};


Edit: I see.

Ideally, you'd have just one linked list implementation that can hold any kind of value, including — and here's the kicker — a compound data structure that has a linked list as one of its fields. In the code you have right now, the inheritance is actually unnecessary as far as I can tell, you're generally duplicating all the hard work of creating a linked list, and you're mixing the linked list data structure with your higher-level object representing the various lists of words.

Here is one possible way I might structure the data structures here:

  • The generic linked list:

    template <typename T>
    class LinkedList { ... };
    
  • A class that uses linked lists to represent whatever list of words you're making:

    class TokenList {
      struct Token {
        string word;
        LinkedList<string> related;
      };
      LinkedList<Token> list;
      // Methods to add/search/remove tokens from the lists and sublists
    };
    

(Also, I suspect the data structure you're actually seeking is a map, but that's another discussion.)


Looks like you're looking for a Has-A relationship and not an Is-A relationship.

I would suggest for your LinkListList to have a List of lists of the first type, instead of using inheritance.


I think your List class needs some virtual functions. It doesn't know anything about ListList, so it can hardly be expected to use the derived class's members.


A virtual function in a base class allows inheritors to provide an override of it. When the base class (or external callers seeing it as the base class) calls the function in a derived instance, it knows to look for that override in the derived class instead of using the one in the base class.

If you control the base List class (as opposed to a supplied framework class) you could restructure it to use virtual functions in key places so that the derived ListList class could redirect them to its own logic while still being accessible to code accessing it as a List--for example, so you could create a ListList and pass it to something expecting a List.

But if you can't change List and it doesn't already have virtual functions you can override, you may not be able to do it. You might have to look for a different (lower) base class, or create ListList (or LinkedList?) as a separate class rather than derived. It could provide a ToList() function to export its contents as a standard List (and a constructor taking a List and/or a From(List) function to import from a List back into a ListList). But it's probably more work to use it that way, depending on what you actually need to do with it that had you looking to derived from List in the first place.

Edited: With the code you've now posted, it looks like inheritance may not be what you actually need, after all, as @rmn points out. So while this answer hopefully explains a little about how virtual functions work (as applicable to question originally posed), it may not apply to what you're really trying to do with the two classes.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜