How to create an object in C++ with proporties?
If the object is an rectangle I want to access the height and the width like this
int height = obj.height;
int width = obj.width;
The object is returned by a function.. So what is the return type of the function?
Create a class Rectangle:
class Rectangle {
private:
int height;
int width;
public:
Rectangle(int h, int w) : height(h), width(w) {} // constructor to initialize width and height
void getHeight() { return height; } // public getters but private attributes to stick to the encapusaltion
void getWidth() { return width; }
};
Have a function returning a rectangle:
Rectangle doSomething() { // the return type is an instance of the class Rectangle
Rectangle r(2, 3); // create a rectangle with a height of 2 and a width of 3
return r; // return the created object
}
int main()
{
Rectangle r = doSomething(); // call your function
cout << r.getHeight() << " " << r.getWidth() << endl; // prompt width and height
}
If you want to access width and height via r.width and r.height change the access specifier private to public. Then you will not need the getters anymore.
Related
Is there a way to assign a variable within a class with a value of a class method?
I was trying the example below, but it is obviously not working. Is there a correct way of doing this?
#include <iostream>
using namespace :: std;
class rectangle
{
public:
rectangle(double h, double w) {
height = h;
width = w;
};
double area(void) {
return height*width;
};
double myarea = (*this).area();
private:
double height, width;
};
int main(void) {
rectangle r(2.5, 3);
cout << "Area is: " << r.area() << endl;
cout << "Area is: " << r.myarea << endl;
return 0;
}
result
Area is: 7.5
Area is: 0
The problem is that member variables are initialized in the order they are declared within the class. Also, your constructor creates the object before you have actually initialized width and height, as you do your initial assignment in the body of the constructor, rather than in an initializer list. Thus, when myarea is initialized (in your code), width and height have not yet been set.
To fix this, you can re-order the members and move the initialization of width and height into a list:
class rectangle {
private:
double height, width; // These will NOW be set before "myarea" is calculated
public:
rectangle(double h, double w) : height{ h }, width{ w } {
// Any assignments done here will be AFTER initialization of "myarea"
}
double area(void) {
return height * width;
}
double myarea = area();
};
Also, you don't need the complex (*this).area() syntax - just area() will do.
EDIT: Another thing to remember is that the setting of myarea by calling the area() function will only be done once (at object creation); if you change either width or height later, you won't (automatically) change myarea.
I dont understand the diffrence between Polymorphism and Inheritance... They Litterarly do the same thing...
Simple Example Of Polymorphism:
class shape {
public:
void setValues(int height_, int width_) {
height = height_, width = width_;
}
protected:
int height, width;
private:
};
class rectangle :public shape, public ThreeDView{
public:
int area() {
return(shape::height*shape::width);
}
float threeDArea() {
return(((shape::height*shape::width)/2)*(std::cos(Z_LENGTH)));
}
};
class ThreeDView{
public:
void setZLength(int value) {
Z_LENGTH = value;
}
int setCompact(bool ans) {
compact = ans;
}
float getZLength() {
return Z_LENGTH;
}
bool getCOMPACT() {
return compact;
}
protected:
float Z_LENGTH;
bool compact;
private:
unsigned char ZCHAR = 'Z';
};
class triangle :public shape {
public:
int area() {
return((shape::height * shape::width) / 2);
}
};
int main(){
rectangle rect2;
triangle trng2;
shape *poly = &rect2;
shape *poly2 = &trng2;
poly->setValues(2,3);
poly2->setValues(5,4);
std::cout << "AREA : " << trng1.area() << "AREA RECT : \n" <<rect1.area() << std::endl;
}
Above example translated to Inheritance:
class shape {
public:
void setValues(int height_, int width_) {
height = height_, width = width_;
}
protected:
int height, width;
private:
};
class rectangle :public shape, public ThreeDView{
public:
int area() {
return(shape::height*shape::width);
}
float threeDArea() {
return(((shape::height*shape::width)/2)*(std::cos(Z_LENGTH)));
}
};
class triangle :public shape {
public:
int area() {
return((shape::height * shape::width) / 2);
}
};
int main(){
rectangle rect2;
triangle trng2;
rect2.setValues(2,3);
trng2.setValues(5,4);
std::cout << "AREA : " << trng1.area() << "AREA RECT : \n" <<rect1.area() << std::endl;
}
Please tell me diffrence. Honestly i dont even see the use of Polymorphism! Thanks for helping!
Here's a version of your first example, that actually uses polymorphism:
#include <iostream>
#include <string>
class shape
{
public:
void setValues(int height_, int width_)
{
height = height_;
width = width_;
}
virtual int area() = 0; // This is needed for polymorphism to work
virtual std::string name() = 0;
protected:
int height;
int width;
};
class rectangle : public shape
{
public:
int area()
{
return height * width;
}
std::string name()
{
return "Rectangle";
}
};
class triangle :public shape
{
public:
int area()
{
return height * width / 2;
}
std::string name()
{
return "Triangle";
}
};
void print_area(shape& poly)
{
std::cout << poly.name() << ' ' << poly.area() << '\n';
}
int main()
{
rectangle rect;
triangle trng;
rect.setValues(2, 3);
trng.setValues(5, 4);
print_area(rect);
print_area(trng);
}
The first big change is that I declare the virtual function area in the shape class. For polymorphism to work, the functions must be declared in the base class as virtual. The "assignment" to 0 is simply telling the compiler that it's an abstract function, and the child-classes must override that function.
The second big change is that I use a function to print the area, one that only takes a reference to the base shape class. You must use references or pointers to the base class for polymrphism to work, not use the actual objects directly like in your example.
This works as expected.
This program contains three parts: the header, the functions for the class and the main part that is interactive. However, it won't compile.
I keep getting the response that there is an expected constructor, destructor or type conversion.
#ifndef BOX_H
#define BOX_H
class Box
{
private:
double height;
double width;
double length;
public:
Box();
double setHeight();
double setWidth();
double setLength();
double getVolume();
double getSurfaceArea();
};
#endif
function.cpp:
#include "Box.hpp"
/**********************************************************************
Box:: Box
This is the default constructor that uses the set methods to initialize each field to 1.
* **********************************************************************/
Box::Box()
{
height = 1;
width = 1;
length = 1;
}
/*
Does anyone know what this section does? Is it another default constructor or is is it even needed?
Box::Box(double height, double width, double length)
{
setHeight(height);
setWidth(width);
setLength(length);
}
*/
double Box::setHeight()
{
return height;
}
double Box::setWidth()
{
return width;
}
double Box::setLength()
{
return length;
}
double Box::getVolume()
{
return height * width * length;
}
double Box::getSurfaceArea()
{
double SurAre = 0;
SurAre = (2 * (length * width)) + (2 * (length * height)) + (2 * (height * width));
return SurAre;
}
main.cpp:
#include <iostream>
#include "Box.hpp" //contains Box class declaration
using namespace std;
int main()
{
Box object;
double Alength;
double Awidth;
double Aheight;
cout << "This program will calculate the area of a box.\n";
cout << "What is the length?";
cin >> Alength;
cout << "What is the width?";
cin >> Awidth;
cout << "What is the height?";
cin >> Aheight;
object.setLength(Alength);
if (!object.setWidth(Awidth))
cout << "Invalid box width entered. \n" << endl;
if (!object.setHeight(Aheight))
cout << "Invalid box height entered. \n" << endl;
cout << "Volume: " << object.getVolume() << endl;
cout << "Surface Area: " << object.getSurfaceArea() << endl;
return 0;
}
Does anyone have an idea about why?
If you uncomment the three-parameter constructor, you will get an error message, because a constructor is a class member, and class members have to be declared inside the class before they can be used or defined outside.
Add the line
Box(double height, double width, double length);
inside your class definition, and then the additional constructor can be compiled also.
C++ has some strange behaviors: if you fail to declare and define a default constructor, it will do it for you. Think autogenerated. It will also define a compiler-generated copy constructor and destructor. It's helpful to understand this, because these things exist whether you define them or not.
You both declared the constructor in the header:
public:
Box();
and defined it in the cpp file:
Box::Box()
You correctly both declared and defined this constructor.
If you want any other constructor, you have to declare it before you can define it as well
public:
Box();
Box(double height, double width, double length); // this is new
and then you can uncomment your definition in the cpp file, and all should be well.
One other style point: the way you've defined your 3 parameter constructor is not great style. What happens is that you construct a Box, and when you do so, you use the default constructor for it's member variables of height, width, and depth. You then call 3 member functions to assign these variables. In C++ you can avoid all this by using an initializer list. The body of your 3 parameter constructor becomes
Box::Box(double height, double width, double length) :
height(height), width(width), length(length)
{}
What this says is "build me a Box, and as you do so, use the value of passed in height for member height, width for member width, length for member length". You save yourself an assignment of 0 as a default value for the member variables and 3 function calls by building your Box "out of the box" as it were with those values. This uses the copy constructor for your member variables rather than their default constructors followed by an assignment.
(technical note: as builtins, doubles technically don't have these constructors, but the semantics behave as if they do, so you can think of them as having them on first order thought.)
This means, additionally, that if you define a copy constructor:
Box(const Box& other);
then you can use that in other classes to initialize a Box in their initializer lists, e.g.
BunchOfBoxes(const Box& firstBox) :
m_firstBox(firstBox)
{}
and it will use your copy constructor from the Box class to do the same sort of initialize-on-build for BunchOfBoxes
You have a problem with your class declaration/definition:
Your setters should have parameters so you can use them as setters.
In your Box.hpp change
double setHeight();
double setWidth();
double setLength();
to
double setHeight(double _height);
double setWidth(double _width);
double setLength(double _length);
Then in your Box.cpp change
double Box::setHeight()
{
return height;
}
double Box::setWidth()
{
return width;
}
double Box::setLength()
{
return length;
}
to
double Box::setHeight(double _height)
{
height = _height;
return height;
}
double Box::setWidth(double _width)
{
width = _width;
return width;
}
double Box::setLength(double _length)
{
length = _length;
return length;
}
I'm a bit confused with classes was hoping some one could explain.
I have a class I'm making to create buttons for a game menu. There are four variables:
int m_x
int m_y
int m_width
int m_height
I then want to use a render function in the class but Im not understanding how i use the 4 int variables in the class and pass it to the function in the class?
My class is like this:
class Button
{
private:
int m_x, m_y; // coordinates of upper left corner of control
int m_width, m_height; // size of control
public:
Button(int x, int y, int width, int height)
{
m_x = x;
m_y = y;
m_width = width;
m_height = height;
}
void Render(SDL_Surface *source,SDL_Surface *destination,int x, int y)
{
SDL_Rect offset;
offset.x = x;
offset.y = y;
SDL_BlitSurface( source, NULL, destination, &offset );
}
} //end class
Where i am confused is how the values created in public:Button is passed to void render I'm not fully sure I've got this right, if i have its pure luck so far because I'm still a little bit confused.
Maybe an example will help:
#include <iostream>
class Button
{
private:
int m_x, m_y; // coordinates of upper left corner of control
int m_width, m_height; // size of control
public:
Button(int x, int y, int width, int height) :
//This is initialization list syntax. The other way works,
//but is almost always inferior.
m_x(x), m_y(y), m_width(width), m_height(height)
{
}
void MemberFunction()
{
std::cout << m_x << '\n';
std::cout << m_y << '\n';
//etc... use all the members.
}
};
int main() {
//Construct a Button called `button`,
//passing 10,30,100,500 to the constructor
Button button(10,30,100,500);
//Call MemberFunction() on `button`.
//MemberFunction() implicitly has access
//to the m_x, m_y, m_width and m_height
//members of `button`.
button.MemberFunction();
}
You might want to spend some time learning C++ before getting too deep into a complex programming project.
To answer your question, The variables initialized in the constructor (Button) are part of the class instance. So they're available within any class method, including Render.
The following compiled code is showing the resulting area of zero. Some how the width and height variables are still remaining as zero even though we set it using the base constructor.
#include <iostream>
using namespace std;
class Shape {
protected:
int width, height;
public:
Shape( int a=0, int b=0)
{
width = a;
height = b;
}
virtual int area()
{
cout << "Parent class area :" <<endl;
return 0;
}
};
class Rectangle: public Shape{
public:
Rectangle( int a=0, int b=0)
{
Shape(a, b);
}
int area ()
{
cout << "Rectangle class area :" <<endl;
return (width * height);
}
};
class Triangle: public Shape{
public:
Triangle( int a=0, int b=0)
{
Shape(a, b);
}
int area ()
{
cout << "Rectangle class area :" <<endl;
return (width * height / 2);
}
};
// Main function for the program
int main( )
{
Shape *shape;
Rectangle rec(10,7);
Triangle tri(10,5);
// store the address of Rectangle
shape = &rec;
// call rectangle area.
cout << shape->area() << endl;
// store the address of Triangle
shape = &tri;
// call triangle area.
cout << shape->area() << endl;
return 0;
}
Output:
Rectangle class area :
0
Rectangle class area :
0
Trying to find out why the area is zero and how to make the pgm to print the actual area ?
The correct syntax is:
Rectangle( int a=0, int b=0) : Shape(a, b)
{ // ^^^^^^^^^^^^
}
You need to call Shape constructor as part of initializer list.
As in your example, if you write it as a statement,
{
Shape(a,b); // <--- no effect on Base part
}
then, a temporary Shape object is created and destroyed, so it has no effect.
your constructor of child class should be like following,
Rectangle( int a=0, int b=0)
:Shape(a, b) //call base class constructor
{
//Shape(a, b); // you are creating new object of shape here , not calling base constructor
}