| Stiffy (9) | |||||
|
Im making a program whereby i have a Square class which is a subclass of Shape class But my program crashes when the subclass tries to access variable from parent class. Here are my codes:
For testing purpose, i only make this computeArea() return the x-coordinate
I did i couple of test, if i were to change "return shapeXCoordi[0];" to "return 123;", it works fine. I also tried changing it to "return shape" but it will not display anything, although this time, it doesnt crash So im guessing there is something wrong when SquareClass is trying to access shapeXCoordi[0] from ShapeClass Can anyone enlighten me on this situation? | |||||
|
|
|||||
| Zhuge (2877) | |
| Have you ever pushed anything back into the vector? The vector defaults to empty so there exist no elements to access if you try to access them immediately. | |
|
|
|
| Stiffy (9) | |
| Yes, in my main it will ask user for inputs for vertices of the Square, so there are 4 x-coordinates. | |
|
|
|
| Disch (8348) | |
|
I suspect you have object slicing and bad casting going on. How is aShape2D defined? And how are you adding elements to it? | |
|
|
|
| Stiffy (9) | |||
|
I have this in my main Shape2D aShape2D[100]; And
| |||
|
Last edited on
|
|||
| Disch (8348) | |||
Okay this is jiving with what I was thinking... but I misread one line of code here:
How is 'aSquare' defined and initialized? | |||
|
|
|||
| Stiffy (9) | |||
|
I only declare it in my main Square aSquare; and its used only in this part
| |||
|
Last edited on
|
|||
| elementary (13) | |||
|
What exactly is variable aSquare? Shouldn't you just call aShape2D[0].computeArea() ? The biggest issue is you have an array of Shape2D objects of only type Shape2D, not any of its derived classes. First, you need an object that is a derived type, such as Square or Circle.
| |||
|
Last edited on
|
|||
| Disch (8348) | |
|
Okay... so I'm confused. If you are computing aSquare's area... then what purpose does the aShape2D array serve? EDIT: And if that is the only time you are using aSquare, then you must not have properly initialized shapeXCoordi and shapeYCoordi... which is why they have zero elements, which is why it's crashing when you try to access them. EDIT2: To clarify what I suspect is the problem: You are putting all your shape data in your aShape2D array. You then try to access it through your aSquare object. But the problem is your aSquare and aShape2D objects are completely different things. You're writing to one variable and then expecting to be able to read it from an entirely separate variable. | |
|
Last edited on
|
|
| Stiffy (9) | |
|
aShape2D is an array class which stores the x and y coordinate of a shape. And the x and y coordinates are store into vector shapeXCoordi and shapeYCoordi. And aSquare is a subclass of Shape2D with a computeArea function. Im suppose to have subclasses for other shapes and each class has diff algorithm for calculating the area but im doing one at a time. I'll post my entire code so u guys could have a better view of what im doing Sorry for making u guys confused cause i dont really know how to explain my situation well =/ | |
|
|
|
| Stiffy (9) | |||
| |||
|
|
|||
| Stiffy (9) | |||
|
@Disch (EDIT2) im using inheritance so im guessing i could get attributes from class Shape2D?
| |||
|
|
|||
| elementary (13) | |||
|
Shape2D aShape2D[100]; This array is problematic. You want an array of different shapes, but this is not the way to do it. To use polymorphism and virtual functions, you need a base pointer/reference of type Shape2D that will point to a derived type (ie. Square, Rectangle, or Cross). In your case, you want an array of pointers/references of type Shape2D that each will point to any derived type you want.
| |||
|
|
|||
| Disch (8348) | |||||||||
|
Okay you have a fundamental misunderstanding here. Polymorphism allows you to access a child object through a parent pointer. It does not allow you to transform a parent object to a child object. You cannot ever transform a variable from one type to another. It simply is not possible in C++. Once you define a variable as a certain type... it is that type forever (or at least until the variable goes out of scope). (You can, however, convert one type to another by transferring it to a DIFFERENT variable... but that's not what you want to do here, so nevermind that -- I only mention it for completeness). With that in mind... when you do this:
This creates a Shape2D object. A Shape2D object is not a Square object. It will never be a Square object.Now... inheritance forms an "is a" relationship between two classes. When you derive Square from Shape2D like you're doing, this implies a few things: 1) Square objects contain everything that Shape2D objects do 2) Square objects may contain more that Shape2D objects, but cannot contain less. 3) Since Squares contain everything Shape2Ds do, Squares can be treated as if they were Shape2Ds. IE: a Square "is a" Shape2D. 4) The "is a" relationship only goes one way. A child is a parent, but a parent is not a child. An easy to visualize example of this is child class Poodle deriving from parent class Dog. All Poodles are also Dogs, but that doesn't mean all Dogs are Poodles. In your example... all Squares are also Shape2Ds. But that does not mean that a Shape2D is a Square. So understanding the "is a" relationship, and realizing that you can't transform the type of an object after it's declared... how can you "dynamically" create an object based on user input? You're trying to do something like this, which is wrong:
This of course is wrong because you don't have a Square or a Cross. You only have a Shape2D. A Shape2D is neither a Square nor a Cross. What you need to do in order to get this to work is to create the object dynamically. The above code is simply creating a Shape2D all the time. We want to create a Square or a Cross depending on user input. We can do this with pointers and the new operator:
The last thing I'll mention is that to prevent memory leaks, anything you new must also be deleted. When you are done using all these objects, you have to go back and delete any one pointer that points to the unnamed object:
Hopefully that clarifies. | |||||||||
|
|
|||||||||
| TheIdeasMan (1564) | |
|
My comment is to do with the unnecessary complexity of the Assn2::main function. It has 10 levels of nesting as a start. I am very sure this could be done much more efficiently. You seem to have combined a menu with all the options code rolled into one big nightmare function that has 190 lines of code. The code to show a menu should be it's own function, the code to process the menu should be a function (with a switch inside). Each option on the menu should call it's own function. There is a bit of a rule that functions should not exceed 80 lines. Other candidates for functions are the code in the body of a loop or in else if clauses. Getting user input and validating it, should be a function. Sometimes it is worth putting something into a function to clarify the meaning, even it is only a few lines long. This can all explained as the "Divide & Conquer" approach. Divide the big problem into smaller bits (the menu) Divide each of these into more manageable parts (A function for each). Keep this concept going until you have something easy to deal with. The other concept is to do with classes and it is called encapsulation. Basically the code do with a particular type of object should be defined in that class. On top of that you can have an interface with virtual or pure virtual functions declared in a base class. Given the other advice posted already, I am guessing you are going to start again (Don't worry - it's not the first time it has happened to any one). One idea you might find handy, is designing your code by writing psuedocode first. Before doing any thing else, write comments describing your methodology. This can be done iteratively - start with very general ideas, then keep go back and fill in more detail, until you are happy to write code. I know this sounds boring, but it is good because it helps to organise your thoughts logically, identify functions, data structures to store data, data types for variables. With any luck it will lead to more elegant & efficient code. Class design is not as simple as what people think it is. You have to consider how they are all are going to interoperate - and that raises a number of questions. Keep in mind the three types of relationships - "IS A", "HAS A" and "USES A". Hope all goes well, interested to see how you get on. | |
|
|
|
| Stiffy (9) | |
| Alright thanks everyone for ur advice, I'm currently still working on it. I'll update u guys again once I havessome results | |
|
|
|
| Stiffy (9) | |||
|
Hi guys, just a little update. I finally got it working by making updating with this code
Thank you Elementary,Disch and TheIdeasMan for your advice! | |||
|
|
|||