// Example program
#include <iostream>
#include <string>
using namespace std;
class circle {
private:
double r;
double const pi=3.14;
public:
circle(double rad){
r=rad;
}
void periArea(){
double p,s;
p=2*pi*r;
s=pi*pi*r;
cout<<"\nS= "<<s<<endl;
cout<<"\nP= "<<p<<endl;
}
friend void changeRad(circle circle, double newrad);
};
void changeRad(circle circle, double newrad){
circle.r=newrad;
}
int main()
{
double inpr,newr;
cout<<"input radius: ";
cin>>inpr;
circle c1(inpr);
c1.periArea();
cout<<"\ninput new radius: ";
cin>>newr;
changeRad(c1,newr);
c1.periArea();
}
I've got this cpp code that has to define a class circle that calculates perimeter and area then using a friend function change the radius and calculate the area and perimeter again. However I get the same p and s values even after the change function.
Crudely, you need to change your function to pass the circle by reference:
void changeRad(circle& circle, double newrad){
(Note the use of &). Otherwise a copy of the circle instance is passed to the function and any changes to that copy will not be reflected in the original.
But, the normal way of doing things is to arrange your code so that you use
c1.changeRad(newr);
at the call site.
Also, your use of a double to store pi to just 3 significant figures is pretty terrible. My favourite way is to use
const double PI = std::atan(1.0) * 4;
since the C++ standard does not define pi for you (M_PI is POSIX, not ISO!).
You have to pass an object the type Circle by reference
friend void changeRad( circle &circle, double newrad);
^^^
Take into account that though it is a valid declaration of a parameter when its name coincides with the name of the type nevertheless this can confuse the reader and the name of the parameter hides the name of the type. So it is better to rename the name of the parameter as for example
friend void changeRad( circle &c, double newrad);
^^
Also it is better to make the function a non-static member of the class. For example
void changeRad( double newrad );
Related
I need to calculate the radius of the circle in the code.
#include <iostream>
#include <cmath>
using namespace std;
class Circle {
float radius;
const float PI=3.14;
public:
Circle(float radius){
}
Circle getRadius()
{
return radius;
}
Circle setRadius(float radius)
{
this->radius = radius / PI;
return radius;
}
float Area()
{
return radius*radius*PI;
}
float Perimeter()
{
return 2*radius*PI;
}
int equal()
{
return Area()==Perimeter();
}
};
int main() {
float r;
cin >> r;
Circle c(r);
cout << c.Perimeter() << endl;
cout << c.Area() << endl;
cout << c.equal() <<endl;
return 0;
}
i tried to use pointers but i cannot figure it out.
In
Circle(float radius){
}
a parameter with the same name as a member variable is not that member variable. Instead, it shadows the member variable, effectively replacing it unless you know where to look. Passing a value into a parameter named radius will not change the value of the member variable named radius, and this leaves the member radius uninitialized.
This means that
float Perimeter()
{
return 2*radius*PI;
}
and the other functions, excluding setRadius, operate on an uninitialized variable and the results will be undefined.
A possible solution is to ensure the member radius is initialized to the value of the parameter radius.
You cannot simply
Circle(float radius){
radius = radius;
}
because there is only one radius, the member has been shadowed, so the parameter radius assigns its value to itself. This is legal code so it compiles, but often the compiler will issue a warning.
Instead use
Circle(float radius) : radius(radius) {
}
This makes use of the Member Initializer List, one of the most important (and seemingly least-taught) features of the C++ programming language. It allows you to safely reuse the term radius because the first radius must be the member radius.
You could also
Circle(float radius) {
this->radius = radius;
}
to explicitly use the member radius, but for more complicated members this approach can be inefficient. All member variables and base classes are initialized before entering the body of the constructor. Afterward the best you can do is assign. This means the member will be default-initialized (if a default constructor exists; if it doesn't you must use the member initializer list), then a temporary variable must be constructed and this temporary is then assigned to the member. potentially a lot of extra work for no benefit.
Side note:
Keep an eye on the this->radius = radius / PI; in setRadius. It is unusual and probably a bug.
I am new to C++. I have this code to create a struct, to show the usage of mutable keyword in C++.
#include <iostream>
using namespace std;
int main()
{
struct
{
mutable double radius;
double PI = 3.142;
double getArea()
{
return (PI * radius * radius);
}
} circle;
const struct circle c1 = {2.0};
circle.radius = 7;
cout << "Area is " << circle.getArea() << endl;
return 0;
}
But I get the following error message when compiling:
error: variable const main()::circle c1 has initializer but incomplete type
Error is at c1 in the line const struct circle c1 = {2.0};. Can anyone point me out the error here.
You don't define a structure named circle, you define a variable named circle. This variable can not be used as a type.
You should do e.g. struct circle { ... }; to define the structure as a type. Then you could do
const circle c1 = { 2.0 };
c1.radius = 7;
std::cout << c1.getArea() << '\n';
There are a few other problems, most notable you don't declare the getArea function as const which means you can't call it on const objects.
When you put the name circle after the right brace at the end of the struct definition, you're declaring a variable.
Put it at the start, after the word struct, to declare a type.
I.e.
struct circle
{
// ...
};
In other news:
You'll need to declare getArea() as const to be able to call it on a const instance, i.e. double getArea() const.
You don't need the return 0; at the end, because that's the default for main. There is no such default for other functions. main is special.
In order to use cout unqualified (as it seems you want to) you can add using namespace std; at the start of the code; it's usually placed after the includes.
mutable is usually not used to allow outside code to treat part of an object as always non-const.
Instead it's used as a device to more easily let a class implementation have some non-const state also when the object appears to be const to outside code. That's called logical constness. For example, the object might cache the result of an expensive computation, even when it's const.
In C++17 and later mutable can also be applied to lambda expressions, where it yields a lambda that can change its state (captured values).
I was playing around with pointer to the base class, and I casted a rectangle pointer into a circle pointer and called the printradius() function from the rectangle! Could someone explain why this is allowed? Thanks.
#include <iostream>
#include <string>
using namespace std;
class Shape {
};
class Circle: public Shape {
private:
double radius;
public:
Circle(double r)
{ radius = r;}
void printradius()
{ cout << "circle's radius is " << radius << endl;}
};
class Rectangle: public Shape {
private:
double width, length;
public:
Rectangle(double l, double w)
{ length = l; width = w;}
};
int main() {
Rectangle r( 2.0, 2.0); // only a rectangle is created
Shape* s = &r; // up cast into a shape
Circle* c = static_cast<Circle*>(s); //down cast into a circle
c->printradius();
}
output:
circle's radius is 2
What do you mean by "allowed"?
The language explicitly states that the result of such static_cast is undefined, so it is not really "allowed" in this case. In order to perform a valid downcast from Shape * to Circle *, you have to ensure that Shape * actually points to Circle or something derived from Circle. Otherwise, the behavior is undefined.
As for why the compiler did not catch it... The compiler cannot possibly catch errors that depend on run-time conditions. In general case the compiler does not know what your s pointer actually points to.
As for why the language even offers such feature... It offers it because it can be extremely useful when one uses it properly.
The static cast is "because I said so.", in other words, trust me, the programmer, that the thing is what I say it is, a circle pointer in this case. When calling the printradius() method, The this pointer is for r, and when printradius() happens to deref looking for a radius, it finds that first double, with a value of 2.0. There is no crash, or reported error from running this way, but as you know, it makes no sense.
Use a dynamic cast and check the value returned. You will see null, because rectangle and circle are not the same.
For a homework assignment we are asked to create two classes: a MyPoint class and a ThreeDPoint class.
Here is my MyPoint class:
#pragma once
#include <math.h>
class MyPoint
{
private:
double x, y;
public:
MyPoint()
{
x = y = 0;
}
MyPoint(double x, double y)
{
this->x = x;
this->y = y;
}
double getX()
{
return x;
}
double getY()
{
return y;
}
double distance(MyPoint pointB)
{
return sqrt((x - pointB.x) * (x - pointB.x)
+ (y - pointB.y) * (y - pointB.y));
}
};
Here is my ThreeDPoint class:
#pragma once
#include "MyPoint.h"
class ThreeDPoint : public MyPoint
{
private:
double z;
public:
ThreeDPoint() // : MyPoint()
{
z = 0;
}
ThreeDPoint(double x, double y, double z) : MyPoint(x, y)
{
this->z = z;
}
double getZ()
{
return z;
}
double distance(ThreeDPoint pointB) // function overloading
{
// x and y are private not protected
return sqrt((getX() - pointB.getX()) * (getX() - pointB.getX())
+ (getY() - pointB.getY()) * (getY() - pointB.getY())
+ (getZ() - pointB.getZ()) * (getZ() - pointB.getZ()));
}
};
And here is main:
#include <iostream>
#include "SignatureBlock.h"
#include "MyPoint.h"
#include "ThreeDPoint.h"
int main()
{
SignatureBlock myBlock;
std::cout << myBlock.toString();
MyPoint pointA(1, 2);
MyPoint pointB(4, 2.5);
std::cout << pointA.distance(pointB) << '\n';
ThreeDPoint point_a(0, 0, 0);
ThreeDPoint point_b(10, 30, 25.5);
std::cout << point_a.distance(point_b) << '\n';
return 0;
}
This code works fine. It is able to calculate the distance between two points in both 2-dimensional and 3-dimensional space. However, in the homework instructions for the ThreeDPoint class, the book says to create
"A constant get function that returns the z value"
and
"A constant distance(const MyPoint&) function to return the distance between this point and the other point in three-dimensional space."
My question is what do they mean by "A constant get function..." and "A constant distance(const MyPoint&) function..."? I understand that you can put const after a function declaration to prevent the function from changing any class members, but why is this necessary here?
Also, why would I pass const MyPoint& to the distance function rather than a ThreeDPoint object? After all we're trying to find the distance between two ThreeDPoints. I read that if you have a parent object parameter in the member function declaration any child of that parent can also be passed to the function, so maybe that has something to do with it.
Lastly, isn't the distance(const MyPoint&) in the instructions missing a name for the MyPoint& object? I did try to type this in and the compiler doesn't mind, but how would I access the members of the object being passed in?
Edit: Also, what purpose does the & serve?
Most importantly, how would I re write my code to follow exactly what the instructions state?
Thanks for reading and thank you for any suggestions anyone might have.
If you live in a world where there are no const objects, it's never necessary to mark methods const. However, it is a good idea. Using const pointers and references is a very good practice when you don't need to change members of an object, and it can help you find design flaws when your program gets bigger.
It's also a good practice to pass references to objects, because passing a reference is usually faster than passing a copy of the object. (It's also in this context that you'll use const references: it tells the caller that you want the object by reference because it's faster, not because you want to change it.)
It's legal to omit argument names, but it has the obvious consequence that you won't be able to use them in your function. It's also a common notation because compilers get rid of argument names when they create function signatures, so you'll often see error messages that look like distance(const MyPoint&) instead of distance(const MyPoint& point).
I can't help you about why they want a const MyPoint& for the ThreeDPoint class. My best guess is that they want you to assume the z component of that point is 0.
I'm learning c++. I have written a small program which should compute the energy
of a N particle system. Up to now I have three small files:
data.h:
class Particle {
public:
double mass;
double charge;
double posx,posy,posz;
};
Particle part[2];
main.cpp:
#include <iostream>
#include "data.h"
using namespace std;
double energy(Particle part );
int main ()
{
double sd;
part[0].mass = 10.0;
part[4].mass = 90.0;
cout << part[0].mass << "\n";
cout << part[4].mass << "\n";
sd = energy(part);
cout << "sd" << sd << "\n" ;
return 0;
}
energy.cpp:
#include <iostream>
using namespace std;
double energy(Particle part)
{
cout << part[0].mass << "\n";
double dummy;
dummy = 2.0;
return (dummy);
}
I have two questions:
1)I want to make visible the Class particle in the function "energy". In other words,
I want to use the variables of the class function (with the values given in "main")
in the energy function.
I have tried as you see energy(Particle part) but it seems Particle is not defined
in that scope.
2)As you see in "data.h" I declared "part" as an array with two members. However,
in "main" I can use more than two members, for instance part[3],part[4]... Why I
could use more members than those I declared?
I am compiling with g++ -o test energy.cpp main.cpp
thanks.
1)I want to make visible the Class particle in the function "energy". In other words, I want to use the variables of the class function (with the values given in "main") in the energy function. I have tried as you see energy(Particle part) but it seems Particle is not defined in that scope.
If I understand you right.. You want to have
Particle part[2];
to be use able in main.cpp and in energy.cpp ?
If yes.. change this to:
extern Particle part[2];
and in energy.cpp add this:
#include "data.h"
Particle part[2];
and you will be able to use
double energy()
{
//main.cpp will have same part
cout << part[0].mass << "\n";
double dummy;
dummy = 2.0;
return (dummy);
}
2)As you see in "data.h" I declared "part" as an array with two members. However, in "main" I can use more than two members, for instance part[3],part[4]... Why I could use more members than those I declared?
Because it's C/C++ ? no range checks. You can do what ever you want.
But if you do, the result will be unexpected.
1)I want to make visible the Class particle in the function "energy".
You should #include "data.h" in the file energy.cpp.
2)As you see in "data.h" I declared "part" as an array with two members.
You probably shouldn't have done that, for two reasons:
You will learn later to avoid declaring global objects. It is legal (and often correct) to do so, but until you learn, you probably want to declare it as a local variable in main.
You should not declare global objects in header files, since they will then be declared in every translation unit that includes the header file.
However, in "main" I can use more than two members, for instance part[3],part[4]... Why I could use more members than those I declared?
By indexing beyond the end of the array, you have invoked "undefined behavior". The system is free to do almost anything (for example, crash, send Bill Gates an email, start a global thermo-nuclear war, &c). Among the infinite variety of things included in "undefined behavior" is the most confusing one of all -- appear to work. That is what happened in your case. You should not count on it continuing to appear to work.
All sorts of things you can do with a class ...
struct Vector3
{
double m_x, m_y, m_z;
};
class Particle
{
public:
double ComputeEnergy() { // return answer }
double GetMass() const { return m_mass; }
double GetCharge() const { return m_charge; }
const Vector3& GetPos() const { return m_pos; }
void SetMass(double mass) { m_mass = mass; }
void SetCharge(double charge) { m_charge = charge; }
void SetPos(const Vector3& pos) { m_pos = pos; }
void SetPos(double x, double y, double z)
{
m_pos.m_x = x;
m_pos.m_y = y;
m_pos.m_z = z;
}
private:
double m_mass;
double m_charge;
Vector3 m_pos;
};
You need to #include "data.h" in energy.cpp. Includes are only processed on a per-file basis, so energy.cpp can't see the header without that.
EDIT: In your function, the parameter part, out-scopes the global definition of part, so the part in your function is not an array. You want:
cout << part.mass << "\n";
1>Include "data.h" in energy.cpp
2> C++ array is very primitive it doesn't has any bound checking so you were able to access part[4].But there is no guarantee that it will work every time.Most of the time program may crash during run-time complaining the memory is corrupt.
To answer the first question, you could simply include data.h in energy.cpp.
#include "data.h"
Unfortunately, you've created "part" in the global space and so each .cpp file will independently create it. When it goes to link the object files, it will see that multiple references to "part" exist. What you can do here is use the "extern" keyword and in data.h, you would simply declare it as an external variable. Or, because you only reference "part" in main.cpp, you could just move the global definition in there and the problem is solved.
Now, when it comes to what you have done in energy.cpp, you've create a separate variable also called "part". When scoping rules are applied, it means that the compiler is going to take the local definition over the global definition. Since you are passing a class object and not a class array, you'll get a compiler error when referencing it like "part[0].mass".
Instead, why are you concerned about the value of the other particle and not the particle you passed in? If you want the mass of a particular Particle object, then you should write it like "part.mass"
Of course, I would argue that what you really want to create is a member function for energy within Particle. Right now, you are currently using classes in a C style struct way. This means that you are missing the ability to use all the object oriented goodness that C++ has to offer. You could do it like this
class Particle
{
protected:
double mass;
double charge;
double posx,posy,posz;
public:
void SetMass(double newMass) { mass = newMass; }
void SetCharge(double newCharge) { charge = newCharge; }
void SetX(double newX) { posX = newX; }
void SetY(double newY) { posY = newY; }
void SetZ(double newZ) { posZ = newZ; }
double GetEnergy() { return 2.0; }
};
To answer your second question, C++ assumes you know more about the memory then it does. There is no bounds checking in GCC(AFAIK) because the memory could be allocated anywhere at any time and deallocated as well. However, unlike other languages, you have to manage the memory yourself. There's a lot of optimizations and C++ trickery that this enables(like declaring a zero sized array for unknown sizes and assigning a block of memory to it).
Cheers!