I need to complete the Rectangle class. Write 3 constructors and a destructor to satisfy the main() below. Use constructor initializers for each constructor.
This is what is done:
class Rectangle
{
float* length;
float* width;
...
???
...
};
int main()
{
Rectangle r1;
Rectangle r2(4.5,2.3);
Rectangle r3(r2);
}
This is how I filled up the rectangle class:
class rectangle
{
private:
float* length;
float* width;
public:
rectangle(); //default constructor
rectangle(double w, double l); //constructor with parameters
rectangle(const rectangle&); //copy constructor
~rectangle(void);
double getWidth(void);
double getLength(void);
double perimeter(void) const;
double area(void) const;
};
...........
...........
...........
int main()
{
rectangle r1;
rectangle r2(4.5,2.3);
rectangle r3(r2);
//statements
}
I just want to know if am doing it right or wrong. Can anyone see if am missing smth or need to add to rectanglr class?!
I think that you are doing wrong because the definition
Rectangle r2(4.5,2.3);
does not have a corresponding constructor. Also take into account that the class in the assignment is named as Rectangle not rectangle.:)
I think that instead of length and width (why did you declare them as pointers?!) you should define four data members that will denote four points of the rectangle.
The declaration and the uses of the three constructors (default constructor, a custom constructor, and a copy constructor) look reasonable. Storing pointers to float does not look reasonable, however: you should just store floats (I would actually store doubles unless I have a reason to assume that there are a huge mount of rectangles). When storing floats, there is actually no need to have a copy constructor or a destructor. If you insist in storing float* and, thus, allocate memory, you shall also implement a copy assignment:
rectangle& rectangle::operator= (rectangle other) {
other.swap(*this);
return *this;
}
void rectangle::swap(rectangle& other) {
std::swap(this->length, other.length);
std::swap(this->width, other.width);
}
Related
I have an object called Grid which is evolving in my main script. This is how I have defined Grid:
class Grid{
public:
std::vector <Polymer> PolymersInGrid; // all the polymers in the grid
std::vector <Particle> SolventInGrid; // solvent molecules in the grid
const int x; // length of x-edge of grid
const int y; // length of y-edge of grid
const int z; // length of z-edge of grid
const double kT; // energy factor
const double Emm ; // monomer-monomer interaction
const double Ess ; // solvent-solvent interaction
const double Ems_n ; // monomer-solvent when Not aligned
const double Ems_a ; // monomer-solvent when Aligned
double Energy;
std::map <std::vector <int>, Particle> OccupancyMap; // a map that gives the particle given the location
Grid(int xlen, int ylen, int zlen, double kT_, double Emm_, double Ess_, double Ems_n_, double Ems_a_): x (xlen), y (ylen), z (zlen), kT (kT_), Emm(Emm_), Ess (Ess_), Ems_n (Ems_n_), Ems_a (Ems_a_) { // Constructor of class
// this->instantiateOccupancyMap();
};
// Destructor of class
~Grid(){
};
...
};
In my main script, my Grid evolves when I apply an operator to Grid.
Grid G = CreateGridObject(positions, topology);
std::cout << "Energy of box is: " << G.Energy << std::endl;
for (int i{0}; i<NumberOfMoves; i++){
// perform evolution
Grid G_test (BackwardReptation(G, 0));
// check if G_test is a good structure
if (G_test is good){
// assign
G = G_test;
}
}
When I do this, I get the error
object of type 'Grid' cannot be assigned because its copy assignment operator is implicitly deleted. copy assignment operator of 'Grid' is implicitly deleted because field 'x' is of const-qualified type 'const int'.
I need to evolve Grid multiple times, check if it is good at each evolution step, and change its contents. How can I do this given that I want the geometry of Grid and the energy surface (Emm, Ess, Ems_n, Ems_a) are to be held const?
edit:
The following addition to my classobject worked:
Grid& operator=(const Grid& t){
return *this;
}
I understand that & is an overloaded operator, can be used to refer to addresses of variables, can be used for rvalues, lvalues. My question is, how does one read the syntax Grid& operator=? What does Grid& mean?
I have a problem with my derived class called Square. A square's sides are always equal, so I want there a way for me to send it to the parent class (Rectangle) in a way that it doesn't call the default constructor, but provides a constructor with 1 parameter. However, it finds a problem that it can't tell the difference between the default constructor and the constructor for when the length and width are the same. Is there any way I can explicitly make sure that the Square constructor doesn't call the default constructor instead of the preferred?
class Rectangle : public Quadrilateral
{
private:
int length{};
int width{};
public:
Rectangle(int len = 1, int wid = 1) : length{ len }, width{ wid }
{
}
Rectangle(int s) : length{ s }, width{ s }
{
}
const int area() { return length * width; }
};
class Square : public Rectangle
{
private:
int side{};
public:
Square(int s = 1) : Rectangle{ s } // Call Rectangle w/ one parameter
{
}
int getSide() const { return side; }
int perimeter() { return 4 * side; }
};```
The problem is that there are two ways to get a Rectangle when you have an int. One is to call the first constructor with wid as the default 1, and the other is to call the single argument constructor.
I would argue that this is the result of using default values for parameters. If you need default values, I'd say just make another overload of the function that accepts one fewer parameter and forwards the call to the other function, passing the default value. This way you'll quickly notice that you have two overloads with the exact same signature (taking one int).
You either:
Make up your mind and decide what Rectangle(int) means (either it's just length with default width, or it's both length and width)
Call the Rectangle constructor with two arguments in the first place in Square(int)
I'm trying to make a program that deals with images, in which I have an image object and an image_view object that references a rectangle region in the image:
class image_view;
class image
{
public:
image(int width, int height);
operator image_view() const;
private:
int m_width;
int m_height;
std::vector<pixel> m_pixels;
};
class image_view
{
public:
image_view(const image& ref, point origin, int width, int height);
image_view(image_view view, point origin, int width, int height);
private:
const image& m_ref;
point m_origin;
int m_width;
int m_height;
};
However, when I tried to copy an image_view, the compiler told me that the operator= member function had been deleted because of the non-static member reference. I naively tried to make my own member function with m_ref = other.m_ref but it didn't work since m_ref is const.
I considered using a smart pointer instead of a reference, but I didn't find a way of making a smart pointer to an already existing object.
One solution I found is the following:
image_view& image_view::operator= (const image_view& other)
{
*this = image_view(other);
return *this;
}
This compiles, but is it a good idea? (I might be wrong, but I feel bad about assigning stuff to *this.) If I do that, does that mean I have to define a destructor (even though I'm not allocating anything), move constructor and move assignment operator to satisfy the rule of 5?
If you want to express a non-owning, non-null wrapper that rebinds on assignment, the easiest way to do that is to use std::reference_wrapper:
class image_view
{
public:
image_view(const image& ref, point origin, int width, int height);
image_view(image_view view, point origin, int width, int height);
private:
std::reference_wrapper<image const> m_ref;
point m_origin;
int m_width;
int m_height;
};
The default copy constructor and assignment operator will do the right thing.
I have been trying to understand the default constructor and i think i get it if it's the only constructor in the class. But what if i have more than one constructor defined in the class. What i am trying to do is to create a class "vector", which would store two dimensional vectors. I need one constructor to set the coordinates to the values given in the main function. I also need a default constructor, which when called, would set the coordinates to 0. I can't seem to figure out how to make both work in the same code
#include <iostream>
#include <string>
#include <cmath>
#include <vector>
#include <algorithm>
using namespace std;
class Vector {
double x_coord, y_coord;
public:
Vector(double x_coord=0, double y_coord=0); //default contructor???
Vector (double x, double y) //normal constructor
{
set_values (x,y);
}
void set_values(double new_x, double new_y) //function to set values for the vectors
{
x_coord=new_x;
y_coord=new_y;
}
double get_x()
{
return x_coord;
}
double get_y()
{
return y_coord;
}
};
I can imagine constructing objects of the class using the following:
Vector v1; // Construct with x = 0, y = 0
Vector v2(10); // Construct with x = 10, y = 0
Vector v3(10, 20); // Construct with x = 10, y = 20
You can accomplish all of that with just one constructor:
Vector(double x=0, double y=0) : x_coord(x), y_coord(y) {}
You don't need the second constructor.
The default constructor is the constructor invoked when you omit the parantheses when defining an instance of the class. Example:
Vector vec;
Here, the default constructor (Vector::Vector(double = 0, double = 0)) is executed.
You can remove the other constructor (Vector::Vector(double, double)) and use this definition for the default constructor:
Vector(double x_coord = 0, double y_coord = 0) {
set_values(x_coord, y_coord);
}
When you pass two arguments, this will be called automatically. Furthermore, an ambiguity is resolved: what if, with those two constructors, you passed two doubles? Which one of them should be called? The compiler would raise an error saying that the constructors are ambiguous.
Notes:
The set_values function does not seem helpful as it does not do any useful work. Use a member initializer list in the constructor instead to improve performance. Also, it is considered good style:
Vector(double x_coord = 0, double y_coord = 0): x_coord(x_coord), y_coord(y_coord) { }
Your extensive use of setters and getters looks... bad. It breaks encapsulation. Provide functions, which do not expose implementation details but perform useful operations such as move.
Nevermind, i figured it all out.
If anyone needs the answer:
You can have the default and other constructors defined in Class
class Vector {
double x_coord, y_coord;
public:
Vector(): x_coord(0), y_coord(0) {}; //default constructor
Vector (double x, double y) //normal constructor
{
set_values (x,y);
}
it's just the way you define your default constructor.
Shape.h
class Shape {
private:
string name;
public:
Shape(name);
string getName();
void setName(string);
};
Triangle.h
class Triangle: public Shape {
private:
int x;
int y;
public:
Triangle(name,int[3],int[3]);
int getX();
int getY();
void setX(int);
void setY(int);
};
Triangle.cpp
Triangle::Triangle(string name,int _x[],int_y[]):Shape(name) {
x[] = _x[];
y[] = _y[];
}
int Square::getX() {
return x
}
int Square::getY() {
return y;
}
void Square::setX(int _x) {
x = _x;
}
void Square::setY(int _y) {
y = _y;
}
i need to create triangle that takes in name and 3 points of (x,y). when i try to create an array of triangle on the main Triangle Tri[50]; i got the following errors
Triangle::Triangle(std::string,int*,int*)
candidates expects 3 arguments, 0 provided
Triangle::Triangle(const Triangle&)
candidates expects 1 argument, 0 provided
can pls help me check what is wrong with my constructor?? is it because i am creating an array of objects that store arrays of x and y? so i need to use references and pointers for it?
When you create
Triangle Tri[50];
it will try to call the default constructor to initialize those elements in your Tri array, however, you did not provide such a default constructor and you did not call the constructor with 3 parameters, therefore, compiler complains.
Meanwhile, you seems to try to directly initialize one array with another inside the constructor of Triangle:
Triangle::Triangle(string name,int _x[],int_y[]):Shape(name) {
x[] = _x[];//^^I don't understand how this will work in practice.
y[] = _y[];
}
There is no direct assignment on arrays in C++, though C++ std::array (since C++11) has overloaded operator=, but this is not true for regular array.