CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 8 of 8
  1. #1
    Join Date
    Jan 2009
    Posts
    23

    Using an undefined class?

    I'm probably going a bit overboard in writing some neural network code as far as OOP goes but I'd like to make it work if possible. The problem I am having is that I have defined classes: CNeuron, CGanglion (a layer in the network), CNetwork, and CLink (a graph edge.... a link from one neuron to another)

    In CLink.h I have "class CNeuron;" before it's definition as one of the attributes is a pointer to a neuron. This works out okay. CNeuron.h includes Clink.h, but in CNeuron.h I have a method that uses CGanglion. So I placed "class CGanglion;" prior to my definition of CNeuron.... but now I get an error. If I place this in CLink.h instead I get an error.... it seems wherever I place it I get an error.

    D:\Visual Studio Projects\ann\Neuron.cpp(41) : error C2027: use of undefined type 'CGanglion'

    Stuff like this makes me still feel like a noob. There must be a solution. Thanks for any help.

    Code:
    /*************************************/
    //CLINK.H
    
    #include <stdlib.h>
    #include <time.h>
    
    class CNeuron;
    
    class CLink  
    {
    public:
    	CLink() {::memset(this,0,sizeof(*this));}
    	~CLink() {}
    
    	double dWeight;
    	CNeuron *pNeuron;
    };
    
    /*************************************/
    //CNEURON.H
    
    #include <vector>
    #include <cmath>
    #include "Link.h"
    using namespace std;
    
    namespace afunc {
    	double identity(double x);
    	double step(double x);
    	double bipolar(double x);
    	double sigmoid(double x);
    	double bisigmoid(double x);
    }
    
    class CGanglion;
    
    class CNeuron  
    {
    public:
    	void Attach(class CGanglion *pLayer);
    	void Fire(void);
    	CNeuron();
    	virtual ~CNeuron();
    
    	double dSummator;
    	double (*pfActivation)(double);
    	vector<CLink> vOutput;
    private:
    	void Repolarize(void) {dSummator = 0.;}
    };
    
    /*************************************/
    //CGANGLION.H
    
    #include "Neuron.h"
    
    class CGanglion  
    {
    public:
    	void Add(int n,bool b);
    	CGanglion();
    	virtual ~CGanglion();
    
    	vector<CNeuron> vNeurons;
    
    };
    I don't understand why it works for one file but not the other.

  2. #2
    Join Date
    Aug 2000
    Location
    New York, NY, USA
    Posts
    5,656

    Re: Using an undefined class?

    Quote Originally Posted by robione View Post
    D:\Visual Studio Projects\ann\Neuron.cpp(41) : error C2027: use of undefined type 'CGanglion'
    Looks like you only have a forward declaration of your class 'CGanglion' in Neuron.cpp.
    While it was enough for its header file, you need to include CGanglion.h in your implemetation file.
    Vlad - MS MVP [2007 - 2012] - www.FeinSoftware.com
    Convenience and productivity tools for Microsoft Visual Studio:
    FeinWindows - replacement windows manager for Visual Studio, and more...

  3. #3
    Join Date
    Oct 2002
    Location
    Singapore
    Posts
    3,128

    Re: Using an undefined class?

    There's nothing wrong in writing neutral network code in OOP. Your header file seem okay except for the function signature for CNeuron::Attach(). There is no need to use the class keyword for pLayer pointer since that you have already forward declared CGanglion.

    If you can show the CNeuron.cpp file, we should be able to spot what is wrong.
    quoted from C++ Coding Standards:

    KISS (Keep It Simple Software):
    Correct is better than fast. Simple is better than complex. Clear is better than cute. Safe is better than insecure.

    Avoid magic number:
    Programming isn't magic, so don't incant it.

  4. #4
    Join Date
    Nov 2008
    Location
    England
    Posts
    748

    Re: Using an undefined class?

    The error is pointing at a file you didn't show us, neuron.cpp. Hard to fix what we cant see

    The use of the keyword class in the attach declaration is superfluous.

    memset should be avoided as a way to initialise class types. You might get away with it here but its not recommended at all. Use the constructor initialiser list to set each member to zero or its default value. memset can only be used on POD types.

    Never bring a whole namespace into the global namespace in a header file. In headers explicitly qualify where needed.
    Get Microsoft Visual C++ Express here or CodeBlocks here.
    Get STLFilt here to radically improve error messages when using the STL.
    Get these two can't live without C++ libraries, BOOST here and Loki here.
    Check your code with the Comeau Compiler and FlexeLint for standards compliance and some subtle errors.
    Always use [code] code tags [/code] to make code legible and preserve indentation.
    Do not ask for help writing destructive software such as viruses, gamehacks, keyloggers and the suchlike.

  5. #5
    Join Date
    Jan 2009
    Posts
    23

    Re: Using an undefined class?

    I was missing '#include "Ganglion.h" ' like VladamirF had said. Thanks guys.... I feel more noobish then ever LOL. This has been quite the brain fart on my part.

    Quote Originally Posted by Kheun View Post
    There's nothing wrong in writing neutral network code in OOP....
    True true... I was thinking (and agreeing with this individual that said) avoiding the overhead of objects by using arrays instead would produce faster code. Of course I don't have a super understanding of what happens underneath the hood during compilation. I do know virtual functions add overhead.... as for the rest I'm not sure. Perhaps he was referring to calling one function to act on one array instead of calling essentially the same function x times where x = number of neurons.

    Not a big deal for small networks but I want to try some things based on what my flat panel is displaying at any given time so that's 1280*800*3 nodes in the input layer alone!!! That said I like OOP just because it separates each unit and it's easier for me to see how things are working.

    Quote Originally Posted by Russco View Post
    The use of the keyword class in the attach declaration is superfluous.

    memset should be avoided as a way to initialise class types. You might get away with it here but its not recommended at all. Use the constructor initialiser list to set each member to zero or its default value. memset can only be used on POD types.

    Never bring a whole namespace into the global namespace in a header file. In headers explicitly qualify where needed.
    The 'class' was there in my attempts to get it working. It wasn't there originally.

    I like using memset on structures. Perhaps it's a bad habit developed because I didn't want to type. It works okay as long as the class doesn't have any virtual functions anywhere (methods, part of attributes, parent classes, etc). Perhaps I should convert it to a struct so the possibility of mistakes down the road are smaller. When I code I usually find my structs contain only POD types.

    I'm pretty new to namespaces and their best practices. I just wanted a way to group all the activation functions together.

  6. #6
    Join Date
    Nov 2008
    Location
    England
    Posts
    748

    Re: Using an undefined class?

    There are only 2 minor differences between classes and structs. That is class default to private and inheritance defaults to private, and with structs, they default to public and inherit publically by default. Therefore both structs and classes can have constructors and use the initilsation list. Just because in this case you can get away with a memset doesn't necessarily make it a good idea.
    Code:
    CLink() {::memset(this,0,sizeof(*this));}
    
    should be replaced by
    
    CLink() : dWeight(0), pNeuron(NULL)
    {}
    Which really looks the most self-documenting? Which is safe in all cases? This is C++ not C. Use constructors not memset.

    As for namespaces, you shouldn't bring a whole namespace into the global scope in a header file else every file you include that header in will have name pollution and it could possibly completely change the meaning of your program if you unknowingly have a name conflict that causes the wrong function to be called or the wrong variable to be accessed. The idea of namespaces is to avoid name conflicts. You can use 'using namespace std' in the implementation file, but in the header file you should qualify names in the std namespace explicitly by prefixing std:: onto the name in question. This advice stands also for user defined namespaces. Avoid name pollution, its likely to bite you in the *** on larger projects so its a good idea to code the right way from the off, just to get into good habits rather than bad.
    Get Microsoft Visual C++ Express here or CodeBlocks here.
    Get STLFilt here to radically improve error messages when using the STL.
    Get these two can't live without C++ libraries, BOOST here and Loki here.
    Check your code with the Comeau Compiler and FlexeLint for standards compliance and some subtle errors.
    Always use [code] code tags [/code] to make code legible and preserve indentation.
    Do not ask for help writing destructive software such as viruses, gamehacks, keyloggers and the suchlike.

  7. #7
    Join Date
    Jan 2009
    Posts
    23

    Re: Using an undefined class?

    Thanks Russco. I had seen ppl do just that (use std:: in .h files) when looking through posts for quite some time. Now I know why.

    Happy Holidays everyone!!

  8. #8
    Join Date
    Apr 1999
    Posts
    27,449

    Re: Using an undefined class?

    Quote Originally Posted by robione View Post
    I like using memset on structures. Perhaps it's a bad habit developed because I didn't want to type.
    It is one habit you should drop when you code in C++.
    It works okay as long as the class doesn't have any virtual functions anywhere (methods, part of attributes, parent classes, etc).
    Not true.
    Code:
    #include <string>
    
    struct foo
    {
       std::string x;
    };
    There are no virtual functions in this struct (std::string has no virtual functions either). Using memset on this struct is undefined behaviour, so a simple addition of a member variable has introduced a bug in your program.

    Initialization lists work all the time -- regardless of what the struct or class consists of.

    Also, using memset() in a C++ application, regardless of where you use it, is not recommended. Instead, there is the std::fill() algorithm function. If you have a good implementation, this algorithm function defaults to memset() for simple types, and one-by-one copying for non-POD types -- so you can't go wrong.

    Regards,

    Paul McKenzie

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured