Thread: Getting "undeclared member" error with derived class

  1. #1
    Ethernal Noob
    Join Date
    Nov 2001
    Posts
    1,901

    Getting "undeclared member" error with derived class

    Basically I have a base class that has its members in a protected block and when I try to access those items in the base class I get the error
    error: `child' undeclared (first use this function)
    Code:
    template <typename T>
    class Node
    {
    
    protected:
        T** child;   //dynamically allocated T array.
        T data;
        size_t size;
    
    public:
        Node(size_t capacity) : size(capacity)
        {
            child = new T*[capacity];
    
            for (size_t i = 0; i < capacity; ++i)
                child[i] = NULL;
        }
    
        Node(size_t capacity, T x) : data(x), size(capacity)
        {
            child = new T*[capacity];
    
            for (size_t i = 0; i < capacity; ++i)
                child[i] = NULL;
        }
    
        virtual ~Node()
        {
            for(size_t i = 0; i < size; ++i)
                delete child[i];
        }
    };
    
    
    template <typename T>
    class BinaryTreeNode : public Node<T>
    {
    public:
        BinaryTreeNode() : Node<T>(2) { }
    
        BinaryTreeNode(T x) : Node<T>(2, x) { }
    
        ~BinaryTreeNode()
        {
            delete child[0];
            delete child[1];
        }
    
    };
    Last edited by indigo0086; 10-06-2007 at 11:55 PM.

  2. #2
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,057
    With extraneous code removed, your problem simplifies to
    Code:
    template <typename T>
    class Node
    {
    protected:
        size_t size;
    };
    
    template <typename T>
    class BinaryTreeNode : public Node<T>
    {
    public:
        BinaryTreeNode()
        {
            size = 0;
        }
    };
    When you remove the templates, the code compiles.
    Code:
    //template <typename T>
    class Node
    {
    protected:
        size_t size;
    };
    
    //template <typename T>
    class BinaryTreeNode : public Node//<T>
    {
    public:
        BinaryTreeNode()
        {
            size = 0;
        }
    };
    On a hunch, using
    Code:
    Node<T>::size = 0;
    in the original version works. Don't ask me why, I'm a C programmer.

    In short, for some reason, you want
    Code:
    template <typename T>
    class BinaryTreeNode : public Node<T>
    {
    public:
        BinaryTreeNode() : Node<T>(2) { }
    
        BinaryTreeNode(T x) : Node<T>(2, x) { }
    
        ~BinaryTreeNode()
        {
            delete Node<T>::child[0];
            delete Node<T>::child[1];
        }
    
    };
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

  3. #3
    The larch
    Join Date
    May 2006
    Posts
    3,573
    By the way, aren't you going to delete the same childs multiple times in BinaryTreeNode because both derived and base class destructor will do that?
    I might be wrong.

    Thank you, anon. You sure know how to recognize different types of trees from quite a long way away.
    Quoted more than 1000 times (I hope).

  4. #4
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    The compiler is correct if it rejects the original code. The C++ standard (Section 14.6.2) requires that all names that are not dependent on template parameters are bound to their present definitions when parsing a template function or class. Only names that are dependent are looked up at the point of instantiation.

    This means that the base class template is not expanded when compiling the derived class template so, in indigo's example code, "delete child[0];" in BinaryTreeNode's destructor looks for something named "child" at global scope (i.e. it looks for ::child[0]). No such thing exists, hence the error.

    The more usual fix is to prefix the members with "this->", viz.
    Code:
    ~BinaryTreeNode()
        {
            delete this->child[0];
            delete this->child[1];
        }
    There is also the incidental issue, noted by anon, that (with the problem affecting compilation fixed) BinaryTreeBode's destructor will delete the children, and then Node's destructor will delete them again. That is formally undefined behaviour.

  5. #5
    Ethernal Noob
    Join Date
    Nov 2001
    Posts
    1,901
    Ok, thanks for the help, like you said I totally got
    Quote Originally Posted by anon View Post
    By the way, aren't you going to delete the same childs multiple times in BinaryTreeNode because both derived and base class destructor will do that?
    this is true, I have gotten rid of the derived class constructor since the base class does the same thing (only one being undefined)

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Two conceptual questions
    By AntiScience in forum C++ Programming
    Replies: 3
    Last Post: 11-01-2007, 11:36 AM
  2. derived class can not access base class protected member?
    By George2 in forum C++ Programming
    Replies: 2
    Last Post: 10-21-2007, 06:32 PM
  3. Calling constructor of the base class of a derived class..
    By CaptainPenguin in forum C++ Programming
    Replies: 5
    Last Post: 02-19-2003, 01:47 PM
  4. Replies: 4
    Last Post: 12-29-2002, 12:29 AM
  5. Troubles overriding a const in a derived class
    By sh0x in forum C++ Programming
    Replies: 5
    Last Post: 10-05-2001, 07:11 PM