Hello I have two questions. First, here is some code. I am new to c++. I have to calculate the square of rectangle by the x,y coordinates of upper left and lower right corner - downRightx, upperLeftx, downRighty, upperLefty, the diagonal, and the sides of rectangle. I must make a function print() that calls other private functions only to show the result. Everything is defined inside the class.
class rectangle {
private:
double uLx, uLy, dRx, dRy;
public:
rectangle() {
cout << "enter x coordinate of upper left corner" << uLx;
cout << "enter y coordinate of upper left corner" << uLy;
cout << "enter x coordinate of down right corner" << dRx;
cout << "enter y coordinate of down right corner" << dRy;
}
~rectangle() {
cout << "Deleting object" << endl;
}
private:
void sides() {
double a, b;
a = sqrt(pow((dRx - uLx), 2));
b = sqrt(pow((dRy - uLy), 2));
}
void facediag() {
double s, d;
d = sqrt(pow((dRx - uLx), 2) + pow((dRy - uLy), 2));
---- 1. //here must be the calculation of square s = a*b
}
public:
void print() {
--- 2. //here I must print the results
}
};
so the question is: How to call a and b parameters from side in facediag() function to calculate s = a*b And how to print the results. Can I write cout << a; cout << d; cout << s, etc. in sides() and facediag() and just call them in print? Or can I print them in print() without writing cout << ... in other functions, but otherwise, another access method.
void facediag(){
//code
cout << s;
cout << d;
}
void sides(){
// code
cout << a;
cout << b;
}
void print()
{
sides();
facediag();
}// not like this, is there another way?
Second question I let Cygwin to be installed at its complete form and at some point I realized that I will run out of hdd and the installation hangs, so I interrupted the installation. How can I uninstall it - just delete the folder or to step through the FAQ in the Cygwin site?
You cannot access local variables from other functions. They only exist while that function executes.
What you can do is define more member functions that compute the values you need, like
double height() const
{ return /* something */; }
double width() const
{ return /* something else */; }
and use those functions where you need a or b.
You CAN call the private function in your OWN class.
But, the variable a and b are local variables, so they will not exist out of the function sides(), you can do the same thing in function facediag() to calculate a and b
Related
I have to solve this " create class for describing triangle and trapeze with ability to return values and finding S of the figures.. declare function which allows comparing S of the both figures.. in main function declare object triangle and trapeze and compare their areas .. " - im trying to translate it from Bulgarian to English sorry if its not translated correctly ..
Anyways I came up with a solution, but when it asks me to enter value for trapeze x2 times and I can't understand why... it always takes the first 3 entered numbers but I want it to ask for input only once .. sorry if the answer is obvious
//
// main.cpp
// compare S of 2 figures
//
// Created by Георгиос Семерджиев on 17/05/22.
//
#include <iostream>
#include <cmath>
using namespace std;
class Trap // trap class with declared functions inside
{
protected:
double a, c, h;
void setValueTrap();
public:
Trap();
void Print();
virtual double S();
}; // end trap class
class Triangle : public Trap // triangle class with declared function for finding s() print and setting value
{
double b;
void setValueTriangle();
public:
Triangle();
void Print();
virtual double S();
double p(); // returning P/2
}; // end triangle class
// trap functions ...
Trap:: Trap()
{
setValueTrap();
}
void Trap::setValueTrap() // trap input function
{
cout << "Trap enter a = "; cin >> a;
cout << "Trap enter c = "; cin >> c;
cout << "Trap enter h = "; cin >> h;
cout << endl;
}
double Trap::S() // trap calculating and returning s()
{
return ( (a+c) * h ) / 2;
}
void Trap::Print() // printing S() for trap
{
cout << "Trap S = " << S();
cout << endl;
}
// Triangle functions ..
Triangle::Triangle():Trap()
{
setValueTriangle();
}
void Triangle::setValueTriangle() // setting value for triangle a,b,c
{
cout << "Triangle a = "; cin >> a;
cout << "Triangle b = "; cin >> b;
cout << "Triangle c = "; cin >> c;
cout << endl;
}
double Triangle::p() // returning P / 2 = p
{
return (a+b+c) / 2;
}
double Triangle::S() // calculating S() of triangle
{
return sqrt(p() * (p() - a) * (p()-b) * (p()-c));
}
void Triangle::Print()
{
cout << "Triangle S = " << S();
cout << endl;
}
// creating function to compare Trap S() and Triangle S()
bool Compare (Trap *F1, Trap *F2)
{
return F1 -> S() < F2 -> S();
} // compare function
int main()
{
Trap* trap = new Trap();
Triangle* triangle = new Triangle();
trap -> Print(); triangle -> Print();
cout << endl;
if (Compare(trap, triangle))
cout << "the Trap S < Triangle S.." << endl;
else
{
cout << "The Trap S > Triangle S.." << endl;
}
return 0;
}
For the Triangle constructor you have:
Triangle::Triangle():Trap()
{
setValueTriangle();
}
That will explicitly invoke the Trap constructor which read input. Then you will read the input for the triangle.
It's often not a good idea to read input in a constructor. It's usually better to only do basic initialization in the constructor and then get input using the fully constructed object.
Note that even if you don't have the explicit invokation of the Trap constructor, this will happen implicitly.
Triangle inherits from Trap, and both of their constructors are called when constructing Triangle object. To avoid this set up a virtual function setValue and call it only in Trap constructor.
This is the beginning of my code that's supposed to be attached to a much larger code where I have to use 3 vectors to determine if I have a triangle, and if so, compute the area with multiple methods(like Heron's formula) for a homework assignment.
My main question is that, given the code below, which should result in sides with lengths of 5/4/3 respectively... why am I getting results of 4.6e-310/6.9e-310/0.
I am aware that my code may not be pretty, and may have gross conceptual errors, but I've only been learning C++ for 3 weeks after studying Fortran for a month.... and I feel super lost trying to do this.
#include <iostream>
#include <math.h>
// design vector class
class Vector {
private:
double Side1() {
return sqrt(pow(p1x-p2x,2)+pow(p1y-p2y));
}
double Side2() {
return sqrt(pow(p2x-p3x,2)+pow(p2y-p3y,2));
}
double Side3() {
return sqrt(pow(p3x-p1x,2)+pow(p3y-p1y,2));
}
public:
double p1x=1.0, p2x=4.0, p3x=4.0;
double p1y=5.0, p2y=9.0, p3y=5.0;
};
// get length
int main() {
double Side1, Side2, Side3;
std::cout << "Side 1 length is " << Side1 << std::endl;
std::cout << "Side 2 length is " << Side2 << std::endl;
std::cout << "Side 3 length is " << Side3 << std::endl;
return 0;
}
There is a couple of errors in your code:
First, your functions are private. This means you cannot ever call these functions, except from within another function of this class. You probably meant to have public funtions and private data members instead:
class Vector {
public:
double Side1() {
return sqrt(pow(p1x-p2x,2)+pow(p1y-p2y));
}
double Side2() {
return sqrt(pow(p2x-p3x,2)+pow(p2y-p3y,2));
}
double Side3() {
return sqrt(pow(p3x-p1x,2)+pow(p3y-p1y,2));
}
private:
double p1x=1.0, p2x=4.0, p3x=4.0;
double p1y=5.0, p2y=9.0, p3y=5.0;
};
Second, you need an object of the type Vector (because your functions are not static members of this class). Then, on this object, you need to call your methods.
int main() {
Vector v; // create object
std::cout << "Side 1 length is " << v.Side1() << std::endl; //note the call operator ()
std::cout << "Side 2 length is " << v.Side2() << std::endl;
std::cout << "Side 3 length is " << v.Side3() << std::endl;
return 0;
}
Your current code creates 3 unitialized double variables, which have nothing in common with your functions (they just share the name).
So I'm working on a school project in C++. The basic idea is, that I have an area containing Tiles (200x200 Tiles).
Every Tile-Object contains a vector with shared pointers of my Creature-Class to display them in a GUI. The Project is a Simulation, so in order to simulate every Creature, we should use a vector containing every Creature. That's why I'm using shared pointers.
The Vector, that is specific for every tile is working without a problem, but the one with every Creature in it, is always empty. That's why I can't continue to work on the simulation.
That's how I place a Creature and try to insert it into the vector
void Presenter::placeCreature(const CreatureType& type) const {
int x = getModel().getTerrain()->getCursorPosX();
int y = getModel().getTerrain()->getCursorPosY();
std::shared_ptr<Creature> creature(std::make_shared<Creature>(type));
TileLand::Climate climate(getModel().getTerrain()
->getTileMap()[x + y * Reference::Terrain::terrainWidth].getClimate());
if (climate == TileLand::deepSea || climate == TileLand::shallowWater) {
if (!creature->isLandCreature()) {
getModel().getCreatures().push_back(creature);
getModel().getTerrain()->getTileMap()[x + y * Reference::Terrain::terrainWidth]
.getCreaturesOnTile().push_back(creature);
logger << INFO << "Placed Creature: " << type.getName() << " on Tile (" << x << "|" << y << ")" << ENDL;
return;
}
} else {
if (creature->isLandCreature()) {
getModel().getCreatures().push_back(creature);
getModel().getTerrain()->getTileMap()[x + y * Reference::Terrain::terrainWidth]
.getCreaturesOnTile().push_back(creature);
logger << INFO << "Placed Creature: " << type.getName() << " on Tile (" << x << "|" << y << ")" << ENDL;
return;
}
}
ui.warn("Falsche Kreatur", R"(Diese Kreatur kann auf diesem Feld nicht platziert werden!)");
creature.reset();
}
That's how I did the vector for creatures per tile. Works fine.
class TileLand {
public:
...
private:
const Climate climate;
std::vector<std::shared_ptr<Creature>> creaturesOnTile;
};
This is where the vector containing every creature is defined.
class Model {
public:
explicit Model(const CreatureList& creatureList);
TerrainModel* getTerrain() const;
CreatureList& getCreatureList();
std::vector<std::shared_ptr<Creature>>& getCreatures();
QPixmap calculateView(int sizeX, int sizeY);
void simStep();
private:
CreatureList creatureList;
std::vector<std::shared_ptr<Creature>> creatures;
TerrainModel* terrain;
int stepCounter;
};
The Constructor of the Model-Class. This one contains the global Creature-Vector as you can see above.
Model::Model(const CreatureList& creatureList) : creatureList(creatureList),
terrain(new TerrainModel()),
stepCounter(0) {
for (CreatureType ty : creatureList) {
ty.getInfoInOneLine();
}
}
std::vector<std::shared_ptr<Creature>>& Model::getCreatures() {
return creatures;
}
Thats where I try to do a simulation step for each creature. But I don't know what the problem is, "creatures" is always empty.
void Model::simStep() {
qDebug("Creature");
for (std::shared_ptr<biosim::Creature> cr : creatures) {
qDebug("BIG");
simPlants(cr);
}
}
I hope someone can at least understand what my problem is I have no idea how to describe it better :/.
Since Presenter::getModel() returns a copy of the Model instance, the getModel().getCreatures().push_back(creature) call adds a creature into the creatures vector of that temporary copy (not the original object). This change is then immediately lost when the temporary copy goes out of scope at the end of the statement.
Either have Presenter::getModel() return a reference (like you did for Model::getCreatures()), or just use :
model.getCreatures().push_back(creature);
I have implemented different classes derived from an abstract class and each one has different methods. The problem is that I have to declare the object only at runtime, so I have to create a pointer to the base class and I can't use the methods of each derived class.
I have created an example to explain better what I mean:
#include <iostream>
using namespace std;
class poligon
{
public:
double h, l;
void setPoligon(double h, double l) {
this->h = h;
this->l = l;
}
virtual double GetArea() = 0;
virtual void GetType() = 0;
};
class triangle : public poligon
{
double GetArea() { return l*h / 2; }
void GetType() { cout << "triangle" << endl; }
double GetDiag() { return sqrt(l*l + h*h); }
};
class rectangle : public poligon
{
double GetArea() { return l*h; }
void GetType() { cout << "rectangle" << endl; }
};
void main()
{
poligon* X;
int input;
cout << "1 for triangle and 2 for rectangle: ";
cin >> input;
if (input == 1)
{
X = new triangle;
}
else if (input == 2)
{
X = new rectangle;
}
else
{
cout << "Error";
}
X->h = 5;
X->l = 6;
X->GetType();
cout << "Area = " << X->GetArea() << endl;
if (input == 2)
{
cout << "Diangonal = " << X->GetDiag() << endl; // NOT POSSIBLE BECAUSE " GetDiag()" IS NOT A METHOD OF "poligon" CLASS !!!
}
}
Obviously the method X->GetDiag() at the end of the main can't be used because it is not a method of the "poligon" class.
Which is the correct implementation of a program with this logic?
Introduce a method in the base class
virtual bool boHasDiagonal(void) =0;
Declare unconditionally in base class:
virtual double GetDiag();
Implement it differently in both derived classes:
virtual bool boHasDiagonal(void) {return true;} // rectangle
virtual bool boHasDiagonal(void) {return false;} // triangle
Change output line:
if (X->boHasDiagonal())
{cout << "Diangonal = " << X->GetDiag() << endl;}
For a nice touch of paranoia (a healthy state of mind for a programmer in my opinion), use concept by Gluttton of a default implementation of GetDiag(), which signals an error (as in his answer here) .
For the case of many poligons, I like the proposal by Rakete1111 in the comment.
Define method in the base class which define implementation throws exception:
class poligon
{
public:
virtual double GetDiag()
{
throw std::logic_error ("Called function with inappropriate default implementation.");
}
};
In class that has meaningful implementation override it:
class rectangle : public poligon
{
double GetDiag() override
{
return diagonale;
}
};
Usage:
int main () {
try {
X->GetDiag();
}
catch (...) {
std::cout << "Looks like polygon doesn't have diagonal." << std::endl;
}
}
You can use dynamic_cast.
dynamic_cast<triangle*>(X)->GetDiag();
Note that you already have a bug: You only create a triangle if input == 1, but you get the diagonal if input == 2. Also, the above is not really safe, because dynamic_cast can return nullptr if the conversion is invalid.
But it would be better to check whether dynamic_cast succeeds, then you could also drop the input == 2 check:
if (triangle* tri = dynamic_cast<triangle*>(X))
std::cout << "Diagonal = " << tri->GetDiag() << '\n';
Use dynamic casting to check if the base class' pointer is actually a triangle, like this:
int main()
{
...
if(triangle* t = dynamic_cast<triangle*>(X))
std::cout << "Triangle's diagonal = " << t->GetDiag() << std::endl;
return 0;
}
PS: I assume that your example is just a draft, since it has some bugs.
You use dynamic_cast to access subclass-methods.
It returns nullptr if it is not derived from the class. This is called down cast, as you are going down the class-tree:
triangle* R = dynamic_cast<triangle*>(X);
if(R) {
cout << "Diagonale = " << R->GetDiag() << '\n';
};
Edit: You can put the declaration in the first line into the if-condition, which goes out of scope outside the if-statement:
if(triangle* R = dynamic_cast<triangle*>(X)) {
cout << "Diagonale = " << R->GetDiag() << '\n';
};
if(rectangle* R = ...) {...}; // reuse of identifier
If you want to allow, that multiple subclasses have the GetDiag function you can inherit from the poligon-class and another diagonal-class. The diagonal-class only defines the GetDiag function and has not really to do with the polygon-class:
class polygon {
// stays the same
};
class diagonal {
virtual double GetDiag() = 0;
};
class triangle : public polygon, public diagonal {
// body stays the same
};
And like above, you access the methods via casting with dynamic_cast but this time you cast to type diagonal. This time it is side cast, because poligon has nothing to do with diagonal, so you are going sideways in the tree.
polygon diagonal
| | |
| |_____________|
| |
| |
rectangle triangle
As others have said, you can use dynamic_cast to change the static type in your program, add a method to the base-class with a pseudo implementation or use some form of type-switching. However, I would consider all these answers as signs of a design flaw in your program and would reject the code. They all encode assumptions about the types existing in your program into the code and pose a maintenance burden. Imagine adding new types of shapes to your program. You then have to search and modify all the places you dynamic_cast your objects.
I think your example hierarchy is wrong in the first place. When you declare a base-class for ploygons, and derive triangles from it, the whole purpose of polymorphism is to be able to treat similar objects identically. So anything that is not common behavior (not implementation) is put in the base-class.
class poligon
{
public:
double h, l;
void setPoligon(double h, double l) {
this->h = h;
this->l = l;
}
virtual double GetArea() = 0;
virtual void GetType() = 0;
};
class triangle : public poligon
{
double GetArea() { return l*h / 2; }
void GetType() { cout << "triangle" << endl; }
double GetDiag() { return sqrt(l*l + h*h); }
};
You explicitly say that I can replace any instance of polygon with an instance of triangle everywhere in your program. This is the the Liskov substitution principle. What about circles? They don't have height and length. Can you use a rectangle everywhere you expect a polygon? Currently you can, but polygons can have more edges, be self-intersecting etc. I cannot add a new edge to a rectangle, otherwise it would be a rectangle anymore.
There are some solutions, but as it is a design question, the solution depends on what you want to do with the objects.
A downcast is usually a sign of a bad design and is rarely needed in practice.
I can't see why it is needed in this particular case. You have discarded the information about which type you have for no reason. An alternative could be:
void printDiagonal(const triangle& tri)
{
std::cout << "Diangonal = " << tri.GetDiag() << std::endl;
}
void process(poligon& p)
{
p.h = 5;
p.l = 6;
p.GetType();
std::cout << "Area = " << p.GetArea() << std::endl;
}
int main()
{
int input;
std::cout << "1 for triangle and 2 for rectangle: ";
std::cin >> input;
if (input == 1)
{
triangle tri;
process(tri);
printDiagonal(tri);
}
else if (input == 2)
{
rectangle rect;
process(rect);
}
else
{
std::cout << "Error\n";
}
}
Live demo.
I am very new to programming, and am near the end of this program, but cannot quite finish the last detail, which I have been stuck on. I am attempting to switch what shape pointer *sp is pointing to, and it seems to me that what I am doing should work, since rectangle and circle both are shapes; however, when I compile, only the value of the color changes. The area of the circle prints instead of the area of the rectangle and the perimeter prints 0. Any help would be greatly appreciated!
#include <iostream>
#include <string>
using namespace std;
double const pi = 3.1519;
class shape {
public:
shape() {};
shape(string);
virtual double getCircumference() {
return 0;
};
virtual double getPerimeter() {
return 0;
};
virtual double getArea() {
return 0;
};
string getColor();
protected:
string color;
};
string shape::getColor() {
return color;
}
class circle : public shape {
public:
circle(double r, string c) {
radius = r;
color = c;
};
double getArea();
double getCircumference();
private:
double radius;
};
double circle::getCircumference() {
return pi * radius * 2;
}
double circle::getArea() {
return pi * radius * radius;
}
class rectangle:public shape {
public:
rectangle(double w, double l, string c) {
width = w;
length = l;
color = c;
};
double getArea();
double getPerimeter();
private:
double length;
double width;
};
double rectangle::getPerimeter() {
return width * 2 + length * 2;
}
double rectangle::getArea() {
return length * width;
}
void change(shape *sp, shape *sp1) {
*sp = *sp1;
}
int main() {
circle mary(3.2, "Green");
shape *sp = new circle(4.5, "Yellow");
cout << "Circle #1 is " << mary.getColor() << endl;
cout << "Circle #1 has an area of " << mary.getArea() << endl;
cout << "Circle #1 has a circumference of " << mary.getCircumference() << endl << endl;
cout << "Circle #2 is " << sp->getColor() << endl;
cout << "Circle #2 has an area of " << sp->getArea() << endl;
cout << "Circle #2 has a circumference of " << sp->getCircumference() << endl << endl;
shape *sp1 = new rectangle(1.0, 2.1, "Red");
change(sp, sp1);
cout << "Rectangle #1 is " << sp->getColor() << endl;
cout << "Rectangle #1 has an area of " << sp->getArea() << endl;
cout << "Rectangle #1 has a perimeter of " << sp->getPerimeter() <<endl<< endl;
}
It’s important to keep in mind what is meant by various different ways of using pointers. In your program, sp refers to the pointer itself—that is, a memory location telling the computer where to find an object. The asterisk in *sp is a ‘dereference’ operator; it takes a pointer and gives you the thing that it is pointing to.
With this in mind, your line *sp = *sp1; is saying, ‘take the thing that sp is pointing to, and set it to be equal to the thing that sp1 is pointing to.’ In other words, you are changing the value of the object pointed to by sp, not the value of sp itself. To point sp at the object pointed to by sp1, you need sp = sp1; with no asterisks.
The other thing to bear in mind is that C++ by default passes function arguments by value: when the function is called, the arguments are copied, and the function operates on the copies. This means that the original arguments themselves cannot be changed by a function that works like this. Adding an ampersand to the argument declaration, like void change(shape *&sp, shape *sp1) causes the first argument to be passed by reference: the object operated on by the function is the same object that was passed in by the calling code. This allows the function to change objects passed as arguments, and for those changes to remain after the function has returned.
Sorry for the long answer: I could have given you a few lines that did what you wanted, but I thought you might appreciate an explanation of the reason why things work the way they do.
If you are trying to change the address of pointers, you must pass pointers by reference. Try this:
void change(shape *&sp, shape *&sp1)
A pointer is passed by value even if it's a pointer.
This means that you are actually passing the address by value, so the argument is a copy of the original argument.
Think about
void sum(int a, int b, int result);
void foo() {
int result;
sum(5,10,result);
}
While you expect to be able to store the result into the variable passed to the sum argument you won't be able to do it since result is passed by value and hence copied. Every modification you do to result inside the method will be local to the method.
That's exactly the same thing, a pointer is nothing more than an address, if you pass it by value then a copy of the address is passed but every modification to the local variable is just local.
That's why you must use references if you want to be able to modify their values, exactly as every other variable, so you would have
void sum(int a, int b, int& result);
void change(shape*& shape1, shape*& shape2);
This, under the hood, will pass the address to the variable which stores the address (a sort of shape**) so the function is able to know where the original argument is located and modify it directly.