Solved

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

Posted on 2000-05-04
18
229 Views
Last Modified: 2010-04-02
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
Comment
Question by:John500
  • 8
  • 3
  • 3
  • +2
18 Comments
 
LVL 7

Expert Comment

by:KangaRoo
ID: 2779791
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
 
LVL 2

Expert Comment

by:abesoft
ID: 2780502
Where is the function implementation for ReadOutputFile?  It should be in the header file, and not in a separate .cpp file.
0
 

Expert Comment

by:JoeDol
ID: 2780998
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
 

Author Comment

by:John500
ID: 2781303
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
 

Expert Comment

by:JoeDol
ID: 2781323
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
 

Author Comment

by:John500
ID: 2781453
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
 

Expert Comment

by:JoeDol
ID: 2781478
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
 

Author Comment

by:John500
ID: 2781732
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
 
LVL 7

Expert Comment

by:KangaRoo
ID: 2781943
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
Do You Know the 4 Main Threat Actor Types?

Do you know the main threat actor types? Most attackers fall into one of four categories, each with their own favored tactics, techniques, and procedures.

 

Author Comment

by:John500
ID: 2782086
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
 
LVL 7

Expert Comment

by:KangaRoo
ID: 2783802
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
 

Author Comment

by:John500
ID: 2784076
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
 
LVL 14

Expert Comment

by:AlexVirochovsky
ID: 2784303
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
 

Author Comment

by:John500
ID: 2784661
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
 

Author Comment

by:John500
ID: 2784670
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
 
LVL 14

Expert Comment

by:AlexVirochovsky
ID: 2786250
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
 

Author Comment

by:John500
ID: 2790003
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
 
LVL 14

Accepted Solution

by:
AlexVirochovsky earned 100 total points
ID: 2795624
>>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

Maximize Your Threat Intelligence Reporting

Reporting is one of the most important and least talked about aspects of a world-class threat intelligence program. Here’s how to do it right.

Join & Write a Comment

IntroductionThis article is the second in a three part article series on the Visual Studio 2008 Debugger.  It provides tips in setting and using breakpoints. If not familiar with this debugger, you can find a basic introduction in the EE article loc…
This article shows you how to optimize memory allocations in C++ using placement new. Applicable especially to usecases dealing with creation of large number of objects. A brief on problem: Lets take example problem for simplicity: - I have a G…
The goal of the tutorial is to teach the user how to use functions in C++. The video will cover how to define functions, how to call functions and how to create functions prototypes. Microsoft Visual C++ 2010 Express will be used as a text editor an…
The goal of the video will be to teach the user the concept of local variables and scope. An example of a locally defined variable will be given as well as an explanation of what scope is in C++. The local variable and concept of scope will be relat…

707 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

11 Experts available now in Live!

Get 1:1 Help Now