Sign in to follow this  
Cornstalks

Nested Classes and Inheritance [c++]

Recommended Posts

Hi, lately I've been working on making a base class, and then make derived classes from the base. In the base class, I declare a nested class, and then in the derived classes I define everything in the nested class (the one from the base). I keep getting errors. Here's my code:
#include <iostream>

class base
{
    public:
        class getCustomMember;
};
 
class derived : public base
{
    public:
        class getCustomMember
        {
            public:
                int setx(int a) { x = a; }
                int getx() { return x; }
        };
    
    protected:
        static int x;
};
 
int main()
{
    derived alpha;
    
    alpha.getCustomMember.setx(5); // Error: invalid use of `class derived::getCustomMember'
    
    std::cout << alpha.getCustomMember.getx(); // Error: invalid use of `class derived::getCustomMember'
}

When I try to compile it says "invalid use of `class derived::getCustomMember'" when I call the setx() ang getx() in main(). Also, if x isn't declared as static, it says "invalid use of nonstatic data member 'derived::x'". I have no idea what I'm doing wrong, and google didn't help. I'd like to not have x static, but if I have to then I guess I have to. Thanks

Share this post


Link to post
Share on other sites
A nested class declares a type not a member variable. Your base and derived objects do not actually contain an object of type getCustomMember, much less an object of that name.

class Foo
{
public:
class Bar {};
};

int main()
{
Foo foo;
Foo::Bar foobar;
}

Share this post


Link to post
Share on other sites
oooohh okay. I see that now. Is there any way to do something like this? I changed it so that getCustomMember was an object of class GetCustomMemberClass (see code).

#include <iostream>

class base
{
protected:
class GetCustomMemberClass;
public:
GetCustomMemberClass getCustomMember;
};

class derived : public base
{
protected:
static int x;

class GetCustomMemberClass
{
public:
int setx(int a) { x = a; }
int getx() { return x; }
};
};

int main()
{
derived alpha;

alpha.getCustomMember.setx(5);

std::cout << alpha.getCustomMember.getx();
}



But now GetCustomMemberClass is incomplete when I create the base class, so it still doesn't work.

Is there any way to get this to work without having templates or virtual functions? Or am I just wasting time?

Thanks again

Share this post


Link to post
Share on other sites
Quote:
Original post by MikeTacular
oooohh okay. I see that now. Is there any way to do something like this? I changed it so that getCustomMember was an object of class GetCustomMemberClass (see code).

*** Source Snippet Removed ***

But now GetCustomMemberClass is incomplete when I create the base class, so it still doesn't work.

Is there any way to get this to work without having templates or virtual functions? Or am I just wasting time?

Thanks again


Couldn't you do:

class Inner
{
//interface
};
class InnerA : public Inner
{
//implementation A
};
class InnerB : public Inner
{
//implementation B
};

class Outer
{
Outer(Inner* pNewInnie);
Inner* innie;
};

int main(int argc, char** argv)
{
Outer a(new InnerA);
Outer b(new InnerB);

return 0;
}



?

[Edited by - templewulf on June 6, 2006 2:41:48 PM]

Share this post


Link to post
Share on other sites
What are you trying to do?

The fact that the CustomMember class in nested inside the derived class does not mean that they share any variables or member functions.

You can do:


#include <iostream>
using namespace std;

class base
{
public:
class CustomMember;
};

class derived : public base
{
public:
class CustomMember
{
public:
int setx(int a) { x = a; }
int getx() { return x; }
} getCustomMember;

protected:
int x;
};

int main()
{
derived alpha;

alpha.getCustomMember.setx(5); // Error: invalid use of `class derived::getCustomMember'

std::cout << alpha.getCustomMember.getx(); // Error: invalid use of `class derived::getCustomMember'
}


But that only solve half the problem. The x variable is still unavailable in the CustomMember class.

Share this post


Link to post
Share on other sites
Sounds like you want something like


class base
{
public:
class CustomMember
{
virtual int setx(int a) = 0;
virtual int getx() = 0;
};
CustomMember* getCustomMember;

base() : getCustomMember(0) {} // ctor
};

class derived : public base
{
public:
class DerivedCustomMember : base::CustomMember
{
public:
int setx(int a) { x = a; }
int getx() { return x; }
} myDerivedCustomMember;

derived() : getCustomMember(&myDerivedCustomMember) {} // ctor

protected:
static int x;
};

int main()
{
derived alpha;

alpha.getCustomMember->setx(5);

std::cout << alpha.getCustomMember->getx();
}




EDIT: source > code :)

Share this post


Link to post
Share on other sites
Seriously, don't waste the effort on something like this.

The only good reason for extracting this thing out into a class would be so that you could make it general purpose. Well, now imagine that you've built your system with a whole bunch of classes, each of which with templated Member members which you can get() and set() freely. But you never got around to making any variants of the get() and set() functions do anything other than raw get and set (if you do, then you have that much more work to do, and you may as well just do it in a "normal" way on a per-class basis, because the generalization didn't get anywhere). And in that case, you are not doing good OO, but telling a lie.

If you really, really, need a member to be both gettable and settable from outside, then just go ahead and make it public. But you should try to avoid this as much as possible, by exposing an interface of member functions that (I know this is a difficult concept for a lot of people) *do something*.

Share this post


Link to post
Share on other sites
The reason I'm trying to do this is because a little bit ago and I messing around with inheritance, and I wrote the following code:

#include <iostream>

class Base
{
protected:
int x;

public:
virtual void setx() { x = 0; }
virtual int getx() { return x; }
};

class Derived : public Base
{
public:
virtual void setx() { x = 99999999; }
virtual int getx() { return -x; }
};

int main()
{
Derived *alpha = new Derived;

Base *beta = alpha;

beta->setx();

std::cout << beta->getx();

std::getchar();

delete alpha;
}



I'm not quite sure if that code is something that I should never ever do again, but it works and I haven't heard else, so I figure its ok...

But there will be more than one type of Derived class, and in each of those Derived classes there will be some special variables (like hWnd for windows, but macs won't have hWnd). I then want to be able to create a Derived class, and have a Base class pointer, just like in the code above. But the Base class won't have any functions for calling gethWnd() (since it's the base), but one of the Derived classes will. That's why I started this topic, to see if there was any way to do this.

I hope I explained it clearly enough.

Share this post


Link to post
Share on other sites
You've got a lot of problems.

1) As a rule of thumb, when your class contains (classes contain) a virtual member function, make the destructor virtual as well. This normally doesn't cost you anything (because of how vtables are implemented), and it will allow you to delete a derived object through a base pointer.

Even if there is nothing for the destructor to do - in the base class just put 'virtual ~Base() {}' (and overload as/if necessary).

2) BUT: don't heap-allocate things if you don't need to. Here you could just instantiate a Derived, and not have to worry about deleting. If you really wanted to demonstrate that polymorphism was working, you could write something like "Derived alpha; Base& beta = α", but in real code there is normally no good reason to do things like that.

3) It's silly to have a (non-const) member that can only take on one possible value.

4) And yeah, don't use raw sets and gets! Make your member functions *do something*. It's not that hard.

Share this post


Link to post
Share on other sites
Zahlman: Thanks a ton. I've heard of polymorphism, and read some stuff on it but never quite understood it. Now that you mentioned it and I look at my last post, I realise that's pretty much what I was doing.

Thank you all for your info. It doesn't look like I could do what I was originally trying to. I'll just have to do it with virtual functions (which wouldn't be a huge pain now that I think of it).

Thanks to all

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this