• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 248
  • Last Modified:

Template Class - Need to write a procedure that will print out info after comparing multiple index (tree) data

Greetings:

This question has two parts.  If the answers aren't resolved easily, I'll increase the points as necessary.

Before I give the details of the second part, I need to know why I get the following error when I call a template class member function within main():

error C2065: 'ReadOutputFile' : undeclared identifier

Here is the class definition:

template <class ListData>
      class DBOutput
      {

            public:

                  void PrintOwners(IndexNode<ListData> *);
                  void ReadOutputFile();



            private:

                  List<ListData>  List;
                  Index<ListData> SSNIndex;
                  Index<ListData> GSNIndex;
                  Index<ListData> SSN_GSNIndex;
      };

Here is the ReadOuptFile() procedure:

template <class ListData>
      void DBOutput<ListData>::ReadOutputFile()
      {
            
            PrintOwners(SSN_GSNIndex.GetRoot());

      }

I'll post any other code when necessary.  Thanks






0
John500
Asked:
John500
  • 8
  • 3
  • 3
  • +2
1 Solution
 
KangaRooCommented:
Remarkable, there seems nothing wrong with the code snippet.

Undeclared identifiers could also be caused by incorrect (declaration) statements preceding the declaration of the function.
0
 
abesoftCommented:
Where is the function implementation for ReadOutputFile?  It should be in the header file, and not in a separate .cpp file.
0
 
JoeDolCommented:
Is your definition of your template class in the same H file as its declaration or is it in a separate CPP file ? I have seem strange behaviors when they are in separate files, and everything works fine if they are in one single H file.
0
The new generation of project management tools

With monday.com’s project management tool, you can see what everyone on your team is working in a single glance. Its intuitive dashboards are customizable, so you can create systems that work for you.

 
John500Author Commented:
JoeDol,

What I usually do is define long(er) functions in the .cpp file.  If they are short & sweet, I define them in the header file.

All my code is presently this way for numerous functions.  I can't see why it would be choking on this one.  

Are you saying I should define the ReadOutputFile() in the header file.  Thus, under my 'public' declarations I would give the full functions definition?

I hate to do it that way, but I'll try it just for experience sake.
0
 
JoeDolCommented:
I know. I don't like to do that too, but it's the only safe way with template and how compilers (VC at least) actually handle them. I have had problems in the past for this reason. But I can't remember if the error was an 'Undeclared identifier'. You don't have to include that in your class declaration. You can also inline the method definition after your class declaration.
0
 
John500Author Commented:
JoeDol,

I modified the header file to look like this:

template <class ListData>
      class DBOutput
      {

            public:

                  void PrintOwners(IndexNode<ListData> *);
                  void ReadOutputFile(){PrintOwners(SSN_GSNIndex.GetRoot());};

            private:

                  List<ListData>  List;
                  Index<ListData> SSNIndex;
                  Index<ListData> GSNIndex;
                  Index<ListData> SSN_GSNIndex;
      };

When I use the in-line method for ReadOutputFile(), it's no big deal right now because there isn't much code in it.  But after I get more code, are you saying I can put this function somewhere else in the header file, like after the class definition?

However, strangely enough, using the in-line method didn't resolve my problem.  What's more amusing is that in the process of reviewing the code, I notice that the other function I call in main (I only have two right now) was not defined properly in the .ccp file.  I had forgot the prefix 'OwnerDB::', when I added it, I ended up getting two errors for main:

void main()
      {
            
            ReadOwnerFile();            

            ReadOutputFile();

            return;

      }

error C2065: 'ReadOwnerFile' : undeclared identifier
error C2065: 'ReadOutputFile' : undeclared identifier

I was able to compile and run the code without a proper definition before I added the ReadOutputFile() procedure???

0
 
JoeDolCommented:
Could you send a complete copy of your code both the cpp for main and your h file with your template ?
ReadOutputFile is a method of your template class, isnt'it ? But in your main you call it like a global function... am i missing something ?
0
 
John500Author Commented:
JoeDol,

This is about my second attempt using templates.  When you say I'm calling the procedure as a global function, how else should I be calling it, or what would be proper?
0
 
KangaRooCommented:
Then VC messes up the error messages. The template definitions should be included in every translation unit with most compilers. Failure to do so would lead to `undefined symbol' errors from the linker, not to `undeclared ...' from the compiler.
0
 
John500Author Commented:
Ok, I guess I needed something like this:

void main()
      {
            

            DBOutput<Owner> Report1;
            OwnerDB Owners;            
      
            Owners.ReadOwnerFile();            

            Report1.ReadOutputFile();

            return;

      }

Let me know if you want to help with the procedure I need to write.
0
 
KangaRooCommented:
Is the problem solved? If so you can award points. It's not that I wouldn't want to help any further, bit it's clearer for everyone if different question reside in different threads. Besides, a new question will get attention from more experts.
0
 
John500Author Commented:
I'll give JoeDol some more time to decide if he wants to continue this.  If not, I'll have to close it out.  My last comment was in response to his point about my function calls being global.
0
 
AlexVirochovskyCommented:
may be i don't understand something, but next code minimum translated:

class  OwnerDB
{
  public:
   void ReadOwnerFile(void);
   OwnerDB *GetRoot(void);
};
template <class ListData>
class DBOutput
{
  public:
   void PrintOwners(ListData *);
   void ReadOutputFile();
  private:
   ListData  List;
   ListData SSNIndex;
   ListData GSNIndex;
   ListData SSN_GSNIndex;
};

template <class ListData>
void DBOutput<ListData>::ReadOutputFile()
{
   PrintOwners(SSN_GSNIndex.GetRoot());
}

void main()
{
  DBOutput<OwnerDB> Report1;
  OwnerDB Owners;

  Owners.ReadOwnerFile();

  Report1.ReadOutputFile();
}
0
 
John500Author Commented:
AlexVirochovsky,

It looks like your code was close.  The two variables (Report1, Owners) needed a little more.  How about I close this question out and except your answer after it compiles?

The code would compile in main() until I included this line:

Report1.ReadOutputFile();

I received the following error for its member function 'PrintOwners()':

error C2440: '=' : cannot convert from 'class ListNode<class OwnerDB<class Owner> > *' to 'class ListNode<class Owner> *'

Here is the code.  I also included the 'Index' class code because it is the class that actually has the 'GetRoot()' member function.  You had it in a different class.  Got any ideas how I can modify the PrintOwner() function to make this work?



void main()
      {

        DBOutput<OwnerDB<Owner> > Report1;
        OwnerDB<Owner> Owners;

        Owners.ReadOwnerFile();

        Report1.ReadOutputFile();

      }



      template <class ListData>
      void DBOutput<ListData>::PrintOwners(IndexNode<ListData> *IndNodPtr)
      {
            
            string Output;
            ListNode<Owner>  *LstNod;
            
            if(!IndNodPtr)
                  return;

            LstNod = IndNodPtr->GetListNode();

            PrintOwners(IndNodPtr->GetRightPtr());      // traverse right subtree

                  Output = LstNod->GetData().GetLast()     + "," +
                               LstNod->GetData().GetSSN()      + "," +  
                               LstNod->GetData().GetGunManuf() + "," +  
                               LstNod->GetData().GetGunSN()    + "\n";
                  
                  WriteToLog(Output);
            
            PrintOwners(IndNodPtr->GetLeftPtr());                  // traverse right subtree
            return;
      }

      template <class ListData>
      class Index{

            public:

                  // Index constructor      
                  Index(){Root = NULL;};

                  // Index destructor
                  ~Index(){DeleteIndex();};

            
                  void AddIndex(string, ListNode<ListData> *);      // add node to index                  
                  void DeleteIndex();                                                // delete the entire index                  
                  void DeleteIndexNode(IndexNode<ListData> *,       // delete one index node                  
                                                 string);
                  IndexNode<ListData> *GetRoot(){return Root;};      // get root

                  ListNode<ListData> *SearchIndexNode(string);      // get ListNode member                   

                  IndexNode<ListData> *SearchIndex(string);            // get IndexNode


            private:

                  // set tree node pointers after deleting a tree node
                  void HookIndexNode( IndexNode<ListData> *,      // child
                                                IndexNode<ListData> *,      // parent
                                                IndexNode<ListData> *);      // current pointer

            private:

                  IndexNode<ListData> *Root;
      };
0
 
John500Author Commented:
AlexVirochovsky,

Although it may be obvious, I forgot to mention that the error appears on the following line within the PrintOwners() function:

LstNod = IndNodPtr->GetListNode();
0
 
AlexVirochovskyCommented:
You code (without errors):

void WriteToLog(std::string Output)
{
}
class  Owner
{
  public:
  Owner GetData();
  std::string GetLast();
  std::string GetSSN();
  std::string GetGunSN();
  std::string GetGunManuf();
};

class  OwnerDB
{
  public:
   void ReadOwnerFile(void);
   OwnerDB *GetRoot(void);
   Owner *GetListNode();
   OwnerDB *GetRightPtr();
   OwnerDB *GetLeftPtr();
};
template <class ListData>
class DBOutput
{
  public:
   void PrintOwners(ListData *);
   void ReadOutputFile();
  private:
   ListData  List;
   ListData SSNIndex;
   ListData GSNIndex;
   ListData SSN_GSNIndex;
};
template <class ListData>
void DBOutput<ListData>::ReadOutputFile()
{
   PrintOwners(SSN_GSNIndex.GetRoot());
}


template <class ListData>
void DBOutput<ListData>::PrintOwners(ListData *IndNodPtr)
{
  std::string Output;
  Owner  *LstNod;

  if(!IndNodPtr)
   return;

  LstNod = IndNodPtr->GetListNode();

  PrintOwners(IndNodPtr->GetRightPtr()); // traverse right subtree

  Output = LstNod->GetData().GetLast()     + "," +
  LstNod->GetData().GetSSN()      + "," +
  LstNod->GetData().GetGunManuf() + "," +
  LstNod->GetData().GetGunSN()    + "\n";

  ::WriteToLog(Output);

  PrintOwners(IndNodPtr->GetLeftPtr()); // traverse right subtree
  return;
}

template <class ListData> class Index{

public:
  // Index constructor
  Index(){Root = NULL;};

// Index destructor
 ~Index(){DeleteIndex();};


 void AddIndex(std::string, ListData *); // add node to index
void DeleteIndex(); // delete the entire index
void DeleteIndexNode(ListData *, std::string);// delete one index node

ListData *GetRoot(){return Root;}; // get root

ListData *SearchIndexNode(std::string); // get ListNode member

ListData *SearchIndex(std::string); // get IndexNode


private:

// set tree node pointers after deleting a tree node
void HookIndexNode( ListData *, // child
ListData *, ListData *); // current pointer

private:

ListData *Root;
};

void main()
{
  DBOutput< OwnerDB> Report1;
  OwnerDB Owners;

  Owners.ReadOwnerFile();

  Report1.ReadOutputFile();

}
Tested with Bc 5.01
Alex
BTW: i hope, i can answer after 1 hour
translation you code.
0
 
John500Author Commented:
AlexVirochovsky,

Notice below you have the 'Get' functions within the 'OwnerDB' class.  I have them in either the 'List' or 'Index' class:


You Wrote:

class  OwnerDB
{
  public:
   void ReadOwnerFile(void);
   OwnerDB *GetRoot(void);
   Owner *GetListNode();
   OwnerDB *GetRightPtr();
   OwnerDB *GetLeftPtr();
};


My Definitions:

template <class ListData>
      class ListNode{

            public:
                  // get next & previous ListNode pointers
                  ListNode<ListData> *GetNextPtr(){return next;};
                  ListNode<ListData> *GetPrevPtr(){return prev;};

                  // set next & previous ListNode pointers
                  void SetNextPtr(ListNode<ListData> * LN){next = LN;};
                  void SetPrevPtr(ListNode<ListData> * LN){prev = LN;};

                  // set ListNode data member
                  void SetData(ListData *LN){Data = LN;};

            private:
                  ListNode<ListData> *prev;
                  ListNode<ListData> *next;
                  ListData Data;
      };

      template <class ListData>
      class Index{

            public:

                  void AddIndex(string, ListNode<ListData> *);      // add node to index
                  void DeleteIndex();                                                // delete the entire index
                  void DeleteIndexNode(string);                               // delete one index node

                  IndexNode<ListData> *GetRoot(){return Root;};      // get root
                  ListNode<ListData> *SearchIndexNode(string);      // get ListNode member
                  IndexNode<ListData> *SearchIndex(string);            // get IndexNode

            private:

                  IndexNode<ListData> *Root;
      };

Are you saying it is necessary to have the 'Get' functions in the OwnerDB class or is there a way to modify the DBOutput class?

0
 
AlexVirochovskyCommented:
>>Are you saying it is necessary to have the 'Get' functions in the OwnerDB class ?

Yes, by  structure of you classes.
And seems me, that tou you original Q.
I have replied. That is added!  
0

Featured Post

Hire Technology Freelancers with Gigs

Work with freelancers specializing in everything from database administration to programming, who have proven themselves as experts in their field. Hire the best, collaborate easily, pay securely, and get projects done right.

  • 8
  • 3
  • 3
  • +2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now