Nested Classes and Inheritance [c++]

Started by
8 comments, last by Cornstalks 17 years, 10 months ago
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
[size=2][ I was ninja'd 71 times before I stopped counting a long time ago ] [ f.k.a. MikeTacular ] [ My Blog ] [ SWFer: Gaplessly looped MP3s in your Flash games ]
Advertisement
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;}
"Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it." — Brian W. Kernighan
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
[size=2][ I was ninja'd 71 times before I stopped counting a long time ago ] [ f.k.a. MikeTacular ] [ My Blog ] [ SWFer: Gaplessly looped MP3s in your Flash games ]
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]
XBox 360 gamertag: templewulf feel free to add me!
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.
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 :)
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*.
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.
[size=2][ I was ninja'd 71 times before I stopped counting a long time ago ] [ f.k.a. MikeTacular ] [ My Blog ] [ SWFer: Gaplessly looped MP3s in your Flash games ]
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.
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
[size=2][ I was ninja'd 71 times before I stopped counting a long time ago ] [ f.k.a. MikeTacular ] [ My Blog ] [ SWFer: Gaplessly looped MP3s in your Flash games ]

This topic is closed to new replies.

Advertisement