In my Object Oriented c++ course, we have to write this class that I have put below.
Point
class Point{
public:
Point( double x = 0, double y = 0 );
double getX() const;
double getY() const;
Point & setX( double x ); // mutator, returning reference to self
Point & setY( double y );
const Point & output() const;
double distance( const Point & other ) const;
private:
double xPoint, yPoint;
}; // class Point
my question is...I can't find any information on how the functions setX, setY, and output should work. They are the same type as the class itself and I have written what I would expect them to look like below. Can anyone tell me what I am doing wrong and maybe some more specifics of how these functions are working?
The setX function should change xPoint in the object, the setY should do the same for the yPoint and output should simply output them.
Point & Point::setX( double x )
{
xPoint = x;
}
Point & Point::setY( double y )
{
Ypoint = y;
}
const Point & Point::output() const
{
cout << xPoint << yPoint;
}
Just add a return *this; at the end of your setX and setY: you are returning a reference to your object, so that for example you can do: p0.setX(1.23).setY(3.45), with of course p0 an instance of Point. In the output function, put a separator between xPoint and yPoint, like a space. You say They are the same type as the class itself: don't confuse a variable type with the type returned by a function/method: the method setX, setY and output return a reference to an instance of the class to which they belong. Note that the reference returned by output is const, so you can do:
p0.setX(1.23).setY(3.45).output();
But not:
p0.output().setX(1.23);
As setX is not a const method (it doesn't declare that it won't modify the data inside the class instance to which it belongs).
You can call instead:
double x = p0.output().getX();
because getX is a const method.
Note: I am not saying you should use the methods in this way, but the point is to show what potentially you can do.
Setters are public metods thats allow you change private members of the class, they don't have return type so setX, setY should be void not Point:
void set(double x); // Declaration
void Point::setX( double x ) // Definition outside Point.h
{
xPoint = x;
}
Same with output should be void, rest is fine you can define it whatever you wish to display it, you can change it like this:
void Point::output() const
{
cout << "(" << xPoint << ", " << yPoint << ")";
}
setX() will probably change the value of the pointX member, and return a reference to the object being acted on.
So an implementation might be something like
Point &Point::setX(double xval)
{
if (IsValid(xval)) pointX = xval; // ignore invalid changes
return *this;
}
This can (assuming other member functions and operators are being used correctly) be used in things like this
#include <iostream>
// declaration of Point here
int main()
{
Point p;
std::cout << p.setX(25).setY(30).getX() << '\n';
}
While this example isn't particularly useful (it shows what is possible) the chaining of member function calls is useful in various circumstances. For example, this technique is actually the basis on which iostream insertion and extraction operators work, and allow multiple things to be inserted/extracted to/from a stream in a single statement.
The documentation of the setX and setY functions says
// mutator, returning reference to self
Your implementation does the mutation, but you've failed to complete the contract that this function is supposed to satisfy: it's supposed to return a reference to itself.
this is a pointer to the object you're invoking the method on, and so adding the line
return *this;
would complete the contract.
This is an aside, but it may help you understand why anyone would want to use such a 'strange' design.
You may be familiar with ordinary assignment being used in ways such as
a = b = 0;
if((result = some_function()) == 0) {
// Do something in the `result == 0` case
} else {
// Do something in the `result != 0` case
}
and other similar things. The first example sets both a and b to be 0. The second example stores the return value of the function call into the variable result, and then branches based on whether that value is 0 or not.
The way this works is that x = y is a binary operator that which has the side effect of copying the value of y into x, and then returns that value (technically a reference to x) so that it may be used in the surrounding expression.
So when you write a = b = 0, this is parsed as a = (b = 0), and has the effect of making b zero, and then evaluates to a = 0 which is then evaluated and makes a zero. Similarly for the branching example.
This is something people like to do when writing code (it's a completely separate topic whether or not this is good style), so when people design new types with operator= methods, they design them to support this usage, by making them return a reference to the object assigned to. e.g.
MyClass& MyClass::operator=(arg a)
{
// Copy the value of `a` into this object
return *this;
}
The other assignment operators, like operator+= also work this way.
Now, when you're used to this usage, it is a small step to extend it to other functions that sort of act like assignment, like setX and setY. This has the additional convenience of making it easy to chain modifications, as in point.setX(3).setY(7).
Related
I have a class like below
class Circle{
private:
int radius;
Circle* next
}
And I gonna creat set/get method...but i have no idea which data type i have to use.
int Circle::getRadius() const{return radius}
or
int& Circle::getRadius() const{return radius}
void Circle::setRadius(int r)
or
void Circle::setRadius(int& r)
CirCle* Circle::getNext() const{return next}
or
Circle& Circle::getNext() const{return *(next)}
void Circle::setNext(Circle& circle)
{
next = new Circle;
next = circle;
}
or
void Circle::setRadius(Circle circle)
{
next = new Circle;
next = circle;
}
or
void Circle::setRadius(Circle* circle)
{
next = circle;
}
I'm famliar with Java quite a lot. And Java argument are all reference. But cpp is quite different so it drive me crazy. Thanks for your help.
First I'd just recommend going through some C++ tutorials. Your question is probably going to get downvoted here because it looks like you really didn't try to search for a solution to your problem, but rather just ask SO for help.
Need to understand a few things with C++. Learn pass by reference vs pass by value. Are primitives passed by reference or by value?
You also should look at pointers. You're kinda mixing up syntax in there a little bit. * is to de reference a pointer. & is to get the memory address of a certain object.
Explore these concepts and you'll find the answer to your question, and learn more about C++.
Try looking at this site for some info.
http://www.learncpp.com/cpp-tutorial/84-access-functions-and-encapsulation/
If you have any other questions, feel free to let me know. :)
Happy to help.
You should use:
int Circle::getRadius() const{return radius}
Why?
First because you don't want your getter to modify your object (that is done by the const after () ), and you don't want caller to your getter to be able to modify your radius either, in fact:
int& Circle::getRadius() const{return radius}
should not even compile. it would have to be:
const int& Circle::getRadius() const{return radius}
In this case the reference to radius returned is const and therefore, the caller cannot modify the radius via this getter.
Although it's totally correct, when dealing with primitive types in C++ one usually prefer to copy rather than to hold const reference. Why? because copy on primitive costs less than have to dereference it each time you need to use it.
Use:
void Circle::setRadius(int r)
Why?
Like before, using an int, prefere to copy the value to use a reference that you'll have to (implicitly) derefence on use.
In this case:
CirCle* Circle::getNext() const{return next}
or
Circle& Circle::getNext() const{return *(next)}
Why? One thing is sure, you won't be able to use the second one, like in the first case your return value will have to be const Circle&. Plus, you want to be able to return a "invalid" value. In C++ not like in Java, you cannot return an "invalid" reference. So the best thing is to return a pointer which will have "NULL" value if "invalid".
After that, if you want your caller to be able to modify the "next Circle" you'll have to go with a Circle* return. If you don't want your caller to be able to modify the result you'll have to go with a const Circle*
const CirCle* Circle::getNext() const{return next}
or
Circle* Circle::getNext() const{return next}
Some people think it's a bad thing to have a const method that return a non const pointer. For certain reasons, I don't, but both are syntaxly correct.
Use:
void Circle::setNext(Circle* circle)
{
next = circle;
}
Why? For your SetNext, it depends on who will have to manage the memory (ie destruction) used by your "next circle" if it's an external class (I think it's the easiest), like a manager for exemple go with that
For your setRadius, simply use:
void Circle::setRadius(int value)
{
radius = value;
}
[Edit: ] Example of Circle class:
Here what would an external manager (like a Circle list) would look like:
class CircleList //Manager as I told
{
public:
Circle* createCircle(int _radius)
{
Circle* circle = new circle(_radius);
//manage here the add to the list of circle
}
void destroyCircle(Circle* _circle)
{
//Manage here the remove of the list
delete _circle;
}
~CircleList()
{
while( first )
{
destroyCircle(first);
}
}
private:
Circle* first = NULL;
};
class Circle
{
public:
Circle(int _radius) : radius(_radius) { }
void setNext(Circle* _circle)
{
next = _circle;
}
Circle* getNext() const
{
return next;
}
void setRadius(int _value)
{
radius = _value;
}
private:
Circle* next = NULL;
int radius = -1;
};
Here, only CircleList manage the list and memory used by circles. If you want to encapsulate even more, make setNext/getNext private and CircleList a friend of circle (once again some will judge, let them :p)
If you wanted to manage memory inside the Circle class, a circle would exist only if its predecessor exist, and if you delete one Circle you would delete all the ones after in the list(I can't see the application this...). In this case you would have something like:
class Circle
{
public:
Circle(int _radius) : radius(_radius) { }
void setNext(int _radius)
{
next = new Circle(radius);
}
void removeNext()
{
delete next;
next = NULL;
}
Circle* getNext() const
{
return next;
}
void setRadius(int _value)
{
radius = _value;
}
~Circle()
{
delete next;
}
private:
Circle* next = NULL;
int radius = -1;
};
Note that you now have a destructor on circle and that when destroying one circle, it destroys all the circle that follow in the list (only way I see to avoid leak and external "holder" of circles)
Plus if you have a really long list, it may cause problems when destroying as a destructor calls (implicitly) the destructor of its successor, you may end up with a stack overflow.
That's why I was telling you that a manager external to the class was the best solution to me, but maybe some other people have better ideas :)
First of all, in Java all are passed by value!
In case of references, it is passed the value of the reference. Because of that it is misunderstood generally.
In case of C++, you can return/pass by value or reference. In your example, int value would be returned by value simply; supposing that probably you would only need its value.
In case of a complex object, you could use reference or pointer. They are actually -almost- the same. You can find sources to look the differences in detail, but here let me tell simply: Pointers are kept in C++ to be compatible with C; references are considered instead. So, you could try to use references mostly.
You need to know the difference of using values by copy and by reference and using pointers.
Passing values by copy, say:
int radius = 2;
setRadius( radius );
Creates a copy of 2 within the function. Whatever changes you do to that value within the function won't change the variable radius that you created outside.
Pointers hold a value that is the memory address of some variable. No matter the type you're using, a pointer only takes up 4 bytes in memory.
int radius = 2;
int *radiusPtr = &radius; // radiusPtr now points to the address of radius
std::cout << *radiusPtr << std::endl; // > 2
setRadius( radiusPtr ); // Passing a pointer to setRadius
Passing by reference is, in a way, similar to pointers but it's defined as "passing the variable itself". You could use a pointer to change the value of the pointed left value, but you can use a reference to change the values of the original variable. You could even use a reference to a pointer to change the original pointer.
int radius = 2;
setRadius( radius ); // Passing by reference is done in the same way as by value, the difference is the method signature -> setRadius( int &radius );
int &radiusRef = radius;
radiusRef = 3;
std::cout << radius << std::endl; // > 3
To answer what to use. Depends on your types and what you need.
//If you use a setter with reference, like
void setRadius( int& radius );
//You cannot pass literal values like
setRadius( 2 );
setRadius( int(2) );
//Only variables/lvalues
int radius = 2;
setRadius( radius );
If you are using a more complex structure then the reference, or a pointer, makes more sense. It's also more efficient to use a reference than it is to copy a huge structure.
The same applies when returning values. If you don't want the user to change the value of your attribute, then a pointer or reference are not the best option. But you could always use a const pointer or reference,
const int *getRadius() const;
const int &getRadius() const;
To prevent the user from changing the radius from outside, yet be able to use the value. The last const means that this function can be called even if you're using a const Circle, or const *Circle or const &Circle.
I'd say for ints you could just use copies, but for more complex structures, like the Circle, consider using references or pointers. In your case, you even store pointers to the next Circle, so a pointer should do.
class Circle{
public:
void SetRadius(int const& value){ radius = value;} // 1
int GetRadius() const {return radius;} // 2
void SetCircle(std::shared_ptr<Circle> const& pCircle) { next = pCircle;} // 3
std::shared_ptr<Circle> GetCircle() { return next; } // 4
private:
int radius;
std::shared_ptr<Circle> next;
}
1 and 3 This is how you write set functions. Period.
2 and 4 Return by value and dont break the encapsulation
3 and 4 NEVER use raw pointers
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.
Lately I'm writing my getter and setters as (note: real classes do more things in getter/setter):
struct A {
const int& value() const { return value_; } // getter
int& value() { return value_; } // getter/setter
private:
int value_;
};
which allows me to do the following:
auto a = A{2}; // non-const object a
// create copies by "default" (value always returns a ref!):
int b = a.value(); // b = 2, is a copy of value :)
auto c = a.value(); // c = 2, is a copy of value :)
// create references explicitly:
auto& d = a.value(); // d is a ref to a.value_ :)
decltype(a.value()) e = a.value(); // e is a ref to a.value_ :)
a.value() = 3; // sets a.value_ = 3 :)
cout << b << " " << c << " " << d << " " << e << endl; // 2 2 3 3
const auto ca = A{1};
const auto& f = ca.value(); // f is a const ref to ca.value_ :)
auto& g = ca.value(); // no compiler error! :(
// g = 4; // compiler error :)
decltype(ca.value()) h = ca.value(); // h is a const ref to ca.value_ :)
//ca.value() = 2; // compiler error! :)
cout << f << " " << g << " " << h << endl; // 1 1 1
This approach doesn't allow me to:
validate the input for the setter (which is a big BUT),
return by value in the const member function (because I want the compiler to catch assignment to const objects: ca.value() = 2). Update: see cluracan answer below.
However, I'm still using this a lot because
most of the time I don't need that,
this allows me to decouple the implementation details of my classes from their interface, which is just what I want.
Example:
struct A {
const int& value(const std::size_t i) const { return values_[i]; }
int& value(const std::size_t i) { return values_[i]; }
private:
std::vector<int> values_;
// Storing the values in a vector/list/etc is an implementation detail.
// - I can validate the index, but not the value :(
// - I can change the type of values, without affecting clients :)
};
Now to the questions:
Are there any other disadvantages of this approach that I'm failing to see?
Why do people prefer:
getter/setters methods with different names?
passing the value as a parameter?
just for validating input or are there any other main reasons?
Generally using accessors/mutators at all is a design smell that your class public interface is incomplete. Typically speaking you want a useful public interface that provides meaningful functionality rather than simply get/set (which is just one or two steps better than we were in C with structs and functions). Every time you want to write a mutator, and many times you want to write an accessor first just take a step back and ask yourself "do I *really* need this?".
Just idiom-wise people may not be prepared to expect such a function so it will increase a maintainer's time to grok your code.
The same-named methods are almost the same as the public member: just use a public member in that case. When the methods do two different things, name them two different things.
The "mutator" returning by non-const reference would allow for a wide variety of aliasing problems where someone stashes off an alias to the member, relying on it to exist later. By using a separate setter function you prevent people from aliasing to your private data.
This approach doesn't allow me to:
return by value in the const member function (because I want the compiler to catch assignment to const objects ca.value() = 2).
I don't get what you mean. If you mean what I think you mean - you're going to be pleasantly surprised :) Just try to have the const member return by value and see if you can do ca.value()=2...
But my main question, if you want some kind of input validation, why not use a dedicated setter and a dedicated getter
struct A {
int value() const { return value_; } // getter
void value(int v) { value_=v; } // setter
private:
int value_;
};
It will even reduce the amount typing! (by one '=') when you set. The only downside to this is that you can't pass the value by reference to a function that modifies it.
Regarding your second example after the edit, with the vector - using your getter/setter makes even more sense than your original example as you want to give access to the values (allow the user to change the values) but NOT to the vector (you don't want the user to be able to change the size of the vector).
So even though in the first example I really would recommend making the member public, in the second one it is clearly not an option, and using this form of getters / setters really is a good option if no input validation is needed.
Also, when I have classes like your second type (with the vector) I like giving access to the begin and end iterators. This allows more flexibility of using the data with standard tools (while still not allowing the user to change the vector size, and allowing easy change in container type)
Another bonus to this is that random access iterators have an operator[] (like pointers) so you can do
vector<int>::iterator A::value_begin() {return values_.begin();}
vector<int>::const_iterator A::value_begin()const{return values_.begin();}
...
a.value_begin()[252]=3;
int b=a.value_begin()[4];
vector<int> c(a.value_begin(),a.value_end())
(although it maybe ugly enough that you'd still want your getters/setters in addition to this)
REGARDING INPUT VALIDATION:
In your example, the assignment happens in the calling code. If you want to validate user input, you need to pass the value to be validated into your struct object. This means you need to use member functions (methods). For example,
struct A {
// getter
int& getValue() const { return value_; }
// setter
void setValue(const int& value) {
// validate value here
value_ = value;
}
private:
int value_;
};
By the way, .NET properties are implemented are methods under the hood.
Suppose I have a class:
class test {
public:
void print();
private:
int x;
};
void test::print()
{
cout<< this->x;
}
and I have these variable definitions:
test object1;
test object2;
When I call object1.print() this happens to store address of object1 and so I get x from object1 printed and when I call object2.print() this happens to store address of object2 and I get x from object2 printed. How does it happen?
Each non-static member function has an implicit hidden "current object" parameter that is exposed to you as this pointer.
So you can think that for
test::print();
there's some
test_print( test* this );
global function and so when you write
objectX.print();
in your code the compiler inserts a call to
test_print(&objectX);
and this way the member function knows the address of "the current" object.
You can think of the this pointer being an implicit argument to the functions. Imagine a little class like
class C {
public:
C( int x ) : m_x( x ) { }
void increment( int value ) {
m_x += value; // same as 'this->m_x += value'
}
int multiply( int times ) const {
return m_x * times; // same as 'return this->m_x * times;'
}
private:
int m_x;
};
which allows you to write code like
C two( 2 );
two.increment( 2 );
int result = two.multiply( 3 );
Now, what's actually happening is that the member functions increment and multiply are called with an extra pointer argument, pointing to the object on which the function is invoked. This pointer is known as this inside the method. The type of the this pointer is different, depending on whether the method is const (as multiply is) or not (as is the case with increment).
You can do something like it yourself as well, consider:
class C {
public:
C( int x ) : m_x( x ) { }
void increment( C * const that, int value ) {
that->m_x += value;
}
int multiply( C const * const that, int times ) const {
return that->m_x * times;
}
private:
int m_x;
};
you could write code like
C two( 2 );
two.increment( &two, 2 );
int result = two.multiply( &two, 3 );
Notice that the type of the this pointer is C const * const for the multiply function, so both the pointer itself is const but also the object being pointed to! This is why you cannot change member variables inside a const method - the this pointer has a type which forbids it. This could be resolved using the mutable keyword (I don't want to get side-tracked too far, so I'll rather not explain how that works) but even using a const_cast:
int C::multiply( int times ) const {
C * const that = const_cast<C * const>( this );
that->m_x = 0; // evil! Can modify member variable because const'ness was casted away
// ..
}
I'm mentioning this since it demonstrates that this isn't as special a pointer as it may seem, and this particular hack is often a better solution than making a member variable mutable since this hack is local to one function whereas mutable makes the variable mutable for all const methods of the class.
The way to think about it is that this is simply a pointer to the memory for whichever object you're currently working with. So if you do obj1.print(), then this = &obj1;. If you do obj2.print(), then this = &obj2;.
this has different values for different objects
Each instance of class test gets it's own copy of member variable x. Since x is unique for each instance, the value can be anything you want it to be.
The variable this, refers to the instance to which it is associated. You don't have to use the variable 'this'. You could just write:
void test::print()
{
cout << x;
}
Guys, I am very new to c++. I have just wrote this class:
class planet
{
public:
float angularSpeed;
float angle;
};
Here is a function trying to modify the angle of the object:
void foo(planet* p)
{
p->angle = p->angle + p->angularSpeed;
}
planet* bar = new planet();
bar->angularSpeed = 1;
bar->angle = 2;
foo(bar);
It seem that the angle in bar didn't change at all.
Note that you are passing bar by pointer, not by reference. Pass-by-reference would look like this:
void foo(planet& p) // note: & instead of *
{
p.angle += p.angularSpeed; // note: . instead of ->
}
Pass-by-reference has the added benefit that p cannot be a null reference. Therefore, your function can no longer cause any null dereferencing error.
Second, and that's a detail, if your planet contains only public member variables, you could just as well declare it struct (where the default accessibility is public).
PS: As far as I can see it, your code should work; at least the parts you showed us.
Appearances must be deceptive because the code should result in foo(bar) changing the contents of the angle field.
btw this is not passing by reference, this is passing by pointer. Could you change the title?
Passing by reference (better) would be
void foo(planet& p) {
p.angle += p.angularSpeed;
}
planet bar;
bar.angularSpeed=1;
bar.angle=2;
foo(bar);
You might also consider a constructor for planet that takes as parameters the initial values of angle and angularSpeed, and define a default constructor that sets them both to 0. Otherwise you have a bug farm in the making due to unset values in planet instances.