Jump to content
  • Advertisement
Sign in to follow this  
sooner123

Class Inheritance Problem

This topic is 2002 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I'm trying to learn about class inheritance and the code below is a combination of my own attempt to understand it and some code from one of the tutorials I'm reading.

I have two questions:
1. Why is this printing out the wrong value for y?
2. Why does the initialization of testBaseClass need to be a pointer? In other words, why BaseClass* testBaseClass and not just BaseClass testBaseClass?


#include <iostream>
#include <stack>

using namespace std;

class BaseClass
{
public:
int x, y;
};

class DerivedClass: public BaseClass
{
public:
DerivedClass(int x, int y)
{
x = x;
y = y;
}
};

int main(int argc, char* argv[])
{
BaseClass* testBaseClass = new DerivedClass(3, 4);
cout << testBaseClass->y;
}
Edited by sooner123

Share this post


Link to post
Share on other sites
Advertisement

1. Why is this printing out the wrong value for y?

How do you expect the compiler to figure out what you mean by x and y, since your class fields have the same name as your constructor parameters? Change the name of either of those to differentiate them, otherwise it's not going to work.

Share this post


Link to post
Share on other sites
Hello

2. Why does the initialization of testBaseClass need to be a pointer? In other words, why BaseClass* testBaseClass and not just BaseClass testBaseClass?


I think you are mistaken. You can do this:
BaseClass testBaseClass = DerivedClass(3, 4);
This variable will be an automatic variable, meaning it is destroyed when you code goes outside the nearest brace "}" (out of scope).

In your example,
BaseClass* testBaseClass = new DerivedClass(3, 4);
The object is allocated at run-time by the "new" operator, and the object stays valid until you deallocate it with the "delete" operator.

Share this post


Link to post
Share on other sites
Ok that fixed my first problem. I intentionally did it that way because I was told by someone that you could do constructor assignments this way and that it would assume the left side was the member and the right side was the parameter.

So I just have one more question.

I want to be able to make a class structure where the base class can have a method AddChild, and can add an arbitrary amount of instances of the derived class.

Basically something like:

base class = widget
derived class = dialogWidget
derived class = buttonWidget

and you create an instance of widget,
then you create an instance of dialogWidget,
then you create an instance of buttonWidget,
then somehow you "add" the dialogWidget instance to the widget instance.
and you then add the buttonWidget instance to the widget instance

Is there an established way of doing this? like a resizable array of widgets INSIDE the widget class declaration? Edited by sooner123

Share this post


Link to post
Share on other sites
The exception being when using the initialization list (as you should if you mean "initialize" rather than "assign in the constructor").

This would be perfectly fine (though probably still confusing to some people)

DerivedClass(int x, int y) : x(x), y(y) {}


Well, actually it wouldn't be, because the compiler would then point out a severe flaw in your code. Why does the derived class have to initialize the base class? How is it a good idea to have instances of the base class being completely uninitialized? And if they aren't supposed to use/need x/y, why are they declared in the base class?


In BaseClass
BaseClass(int x, int y) : x(x), y(y) {}

In DerivedClass
DerivedClass(int x, int y) : BaseClass(x,y) {}


About 2): Because polymorphism only works with pointers/references. C++ is too low level to hide such details from you, so when you use actual instances, you're dictating the exact memory layout of the class in question. When using the base class, everything beyond what is part of the base class is cut off. Because it can be annoying to fiddle with pointers just for that, you might want to use smart pointers for that (though that still won't get you correct behavior when assigning/copying). Edited by Trienco

Share this post


Link to post
Share on other sites

So I just have one more question.

I want to be able to make a class structure where the base class can have a method AddChild, and can add an arbitrary amount of instances of the derived class.

Basically something like:

base class = widget
derived class = dialogWidget
derived class = buttonWidget

and you create an instance of widget,
then you create an instance of dialogWidget,
then you create an instance of buttonWidget,
then somehow you "add" the dialogWidget instance to the widget instance.
and you then add the buttonWidget instance to the widget instance

Is there an established way of doing this? like a resizable array of widgets INSIDE the widget class declaration?


The C++ standard library is the established way of doing this (google for std::vector). Vectors are templated so that you can specify it to contain pointers to your base widget class and store the pointers in there (vectors are resizable arrays). So push the widget pointers passed into the AddChild function into the vector to have a collection of pointers to widgets.

Share this post


Link to post
Share on other sites
This is the example code they gave in the problem that should work if I implement the class structure properly:


//create the main object
BaseClass* testParentClass = new UpperDerivedClass(3, 4);
//create child objects
BaseClass* testChildClass1 = new LowerDerivedClass("john", 1, 2);
BaseClass* testChildClass2 = new LowerDerivedClass("mark", 7, 5);
//add child objects
testParentClass->AddChild(testChildClass1);
testParentClass->AddChild(testChildClass2);
testParentClass->RemoveChild(testChildClass1);


And though I understand everything else, I have no idea how to approach this part. At first I thought you'd just have an array of type BaseClass within the definition of BaseClass, but the way the example code add's children isn't as if it's an array at all. It references the added children by name. I can't think of any way this could work.

At no point is anything referenced with an index. Not during the add or a remove. So isn't this something different from an array or vector? Edited by sooner123

Share this post


Link to post
Share on other sites
The point is to show you that you can have a pointer to a BaseClass point to a Derived class. If it wasn't a pointer, you would literally have a BaseClass in Memory, and you can't turn the BaseClass you already have into a DerivedClass. The pointer, on the other hand, isn't in memory, and thus by using the new operator you're allocating memory for it to use. The BaseClass pointer can point to anything that's a BaseClass, so when you create a "new DerivedClass" you're allocating the memory that the BaseClass pointer points too.

The reason that you output TestBaseClass->y is to show that when you allocated memory for a DerivedClass on a BaseClass pointer, you used the DerivedClass constructor and not the BaseClass instructor, which becomes important later if you use virtual funtions.

Also, I believe linked lists are becoming relatively pointless with std::vectors and std::lists.

A std::vector, at first sight, seems like a resizable array, however it is much more than that. It has many funtions and operators that make it far more useful and versatile than an array. Unless I have to use an array, I generally use an std::vector instead.

std::list's are doubly-linked list. Unless you have special requirements for your linked list or need more than a doubly linked list (Which is very rare), this is literally the standard linked list, and unless it is a learning experience there is no point to program your own. (Programming your own linked list as a learning experience is very rewarding, however, and lets you understand the inner workings of linked lists / arrays / vectors far better). Edited by superman3275

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!