I'm new to C++ and I have a task:
create a class that represents a point on a 2D coordinate plane and then create 3 constructors: one that will define both coordinates and a name (consisting of a single character), two others - a name and one coordinate.
I have no idea how to differentiate inputting x and y. Here's my code:
#include <iostream>
class Point{
public:
Point(char n,double i_x, double i_y) : name(n),x(i_x), y(i_y){}
Point(char n,double i_x) : name(n),x(i_x){}
void print(){
std::cout << name << "("<< x <<","<< y <<")"<< std::endl;
}
private:
double x;
double y;
char name;
};
int main(void){
Point p('A',12);
p.print();
return 0;
}
I understand that I can do this:
Point(char n,double i_x) : name(n),x(i_x){}
Point(double i_y, char n): y(i_y), name(n){}
But, is there a way to make it without changing the structure of the constructor?
And, are there any other mistakes or suboptimal elements I've made?
Here's the full text of the task (may be quite weird, I'm not not very good at translating from my language). The part I'm asking about is in bold:
Laboratory work number 2. Classes.
Before proceeding to the task, read the text in full.
Create a program that defines the 2D point class, which has two fields and three constructors (the first one specifies two coordinates, the others only one). Create a triangle class that contains three points: A, B, C. Define in the triangle one constructor and methods for determining: area, lengths of each side, perimeter.
In the main function, define the 3 points, create the triangle and output all the values we can get using the methods.
Important: fields must be private, methods can be both private and public. If some method will not be private, it is worth explaining why it is public.
Create a program that defines the 2D point class, which has two fields and three constructors (the first one specifies two coordinates, the others only one)
Could be that I miss something, but the only simple way to realize this is the way you already found:
Point(char n,double i_x) : name(n),x(i_x){} Point(double i_y, char n): y(i_y), name(n){}
However, this is very user unfriendly. A caller must remember which constructor initializes wich coordinate:
Point p1('A',12); // x or y coordinate?
Point p2(42,'B'); // x or y coordinate?
As a sidenote, you should initialize both coordinates in both constructors above, and you should list members in the initializer list in the order they are defined in the class (because thats the order in which they are initialized):
Point(char n,double i_x) : x(i_x),y(0),name(n) {}
Point(double i_y, char n): x(0),y(i_y),name(n){}
Note that this doesn't fix the problem for the caller mentioned above.
There are ways to make it more obvious to the caller which coordinate they are passing while staying with the two constructors. Though, they add more complexity for little gain in this particular example. Just for the sake of completeness, I mention that you could use tags:
struct x_tag{};
struct y_tag{};
// and then...
Point(x_tag,double i_x,char n) : x(i_x),y(0),name(n) {}
Point(y_tag,double i_y,char n): x(0),y(i_y),name(n){}
// user
Point p1(x_tag{},1,'A');
If it wasn't x
and y
but two quantities that cannot be used interchageably at all (eg amount of bananas and amount of apples) you could introduce types for the parameters themself (struct banana_quantity { int value; }
and same for the apples).
The more idiomatic way would be to not follow the instructions literally, but provide static methods with speaking names (sometimes refered to as "named constructors", but techincally they aren't constructors):
class Point{
public:
Point(char n,double i_x, double i_y) : x(i_x), y(i_y),name(n){}
static Point PointFromX(double i_x, char n) { return {n,i_x,0}; }
static Point PointFromY(double i_y, char n) { return {n,i_y,0}; }
// etc...
};
What your tutor actually expects you to write I cannot tell you. Unfortunately, requiring students to write non idiomatic C++ is not uncommon. However, you should ask them. When requirements are not clear your customers want you to ask rather than implement something based on speculations.