I've been trying to make an class with an array of objects created dynamically. I overloaded the operator + to add (only this for now) a new object to a group of objects (class to class). THe problem is when I read the data in the array, I get all sorts of big numbers . Here is the code:
#include<iostream.h>
class Figura {
public:
int x, y, poz;
int tip; //1 = punct ; 2 = dreapta; 3 = dreptunghi
Figura() { };
Figura(const Figura&) { };
};
class Grup {
private:
int nr_elemente;
Figura *figuri;
public:
int i;
Grup(int nr_el) {
nr_elemente = nr_el;
figuri = new Figura[nr_elemente];
i = 1;
}
~Grup() {};
Grup(const Grup&) {};
int _nr_elemente() {
return i;
}
void adauga_element(Figura fig) {
if( i <= nr_elemente)
figuri[i++] = fig;
else
cout<<"Grupul a atins numarul maxim de figuri.";
}
void afiseaza_elemente() {
for(int j = 1; j <= i; j++)
cout<<"Figura nr : "<<j<<"tip: "<<figuri[j].tip<<figuri[j].x<<" "<<figuri[j].y<<" "<<figuri[j].poz;
}
friend Grup operator+(const Figura& fig1, const Figura& fig2) {
return fig1.poz + fig2.poz;
};
friend Grup operator+(const Grup& gr1, const Grup& gr2) {};
void operator+(const Figura& fig);
friend Grup operator*(const Grup& fig) {};
};
void Grup::operator+(const Figura& fig) {
Grup::adauga_element(fig);
}
class Punct : public Figura
{
public:
Punct(int poz) {
Punct::tip = 1;
Punct::poz = poz;
}
};
class Segment : public Figura
{
public:
Segment(int poz, int x) {
Segment::tip = 2;
Segment::poz = poz;
Segment::x = x;
}
};
class Dreptunghi : public Figura
{
public:
Dreptunghi(int poz, int x, int y) {
Dreptunghi::tip = 3;
Dreptunghi::poz = poz;
Dreptunghi::x = x;
Dreptunghi::y = y;
}
};
void main(void) {
Grup gr(1);
Punct pct(1);
Segment sgm(3, 5);
gr + pct;
gr + sgm;
//cout<<gr.i;
cout<<sgm.x;
gr.afiseaza_elemente();
}
Array indexes run from 0 to N - 1, when N is the array size. The following code will result in out of bounds array access:
void adauga_element(Figura fig) {
if( i <= nr_elemente)
figuri[i++] = fig;
else
cout<<"Grupul a atins numarul maxim de figuri.";
}
Change to:
if( i < nr_elemente)
Same problem in afiseaza_elemente().
As you have dynamically allocated members a destructor must delete[] the dynamically allocated array and a copy constructor and assignment operator need to be correctly implemented, or declared private to prevent copying. As this is C++, consider using std::vector<Figura> instead of an array.
A more simple example would improve understanding.
In any case, your problem is known as object slicing.
In short, you cannot put a derived object in an array of base objects.
To solve the problem you can change the figuri data member to be an array of pointers to Figura:
Figura ** figuri;
// ...
figuri = new Figura*[nr_elemente];
You're not initializing any members. You should do that in the constructor.
For example:
Punct pct(1);
only initializes the members tip and pos, but x and y will contain garbage values, which you probably end up seeing.
You also shouldn't be using a dynamically allocated array as a member - Figura *figuri; but a std::vector. This would save you also from the undefined behavior you're encountering when adding new figures.
Also, note that your destructors and copy constructors have no implementation, which is a source for bugs.
void adauga_element(Figura fig)
passes the object fig is passed by value, so a copy constructor should be implemented.
Related
I've looked around and only found a solution for either problem, which conflicts with the other.
I have
class A with some const member and other members that need to be initialized
class B with some constructor and a 2D array of A's
like this:
class A {
public:
A();
A(int t, int u);
const int x = 5;
private:
int _t;
int _u;
}
class B {
public:
B();
A a[50][500];
}
A::A() {
//nothing here
}
A::A(int t, int u) {
_t = t;
_u = u;
}
B::B() {
for (int i=0; i<50; i++)
for(int j=0; j<500; j++)
a[i][j] = A(i, j);
}
Now, this doesn't work because A has a const member, so the assignment fails because all the a's have already been default constructed, I obviously don't want to code 25000 initializer values in the member initializer list of B so that is out of the question.
I need the default initializer because otherwise the constructor of B will throw an error that i can't default initialize the array so i need some way to reassign the array with a newly constructed object of A.
How could I accomplish this?
This is what you want?
class A {
public:
A();
A(int t, int u);
const int x = 5;
A& operator=(const A& a);
private:
int _t;
int _u;
};
class B {
public:
B();
A a[50][500];
};
A::A() {
//nothing here
}
A& A::operator=(const A& a) {
_t = a._t;
_u = a._u;
}
A::A(int t, int u) {
_t = t;
_u = u;
}
B::B() {
for (int i=0; i<50; i++)
for(int j=0; j<500; j++)
a[i][j] = A(i, j);
}
You are just missing the = operator
If you want to avoid default-initializing your array, you can use std::vector<std::vector<A>> and populate it in B's constructor :
class A {
public:
A(t, u);
const int x = 5;
private:
int _t;
int _u;
}
class B {
public:
B();
std::vector<std::vector<A>> a;
}
A::A(t, u) {
_t = t;
_u = u;
}
B::B()
: a(50) { // a will contain 50 empty rows
for (int i=0; i<50; i++) {
a[i].reserve(500); // allocates enough space in each row for at least 500 elements
for(int j=0; j<500; j++)
a[i].emplace_back(i, j); // constructs value in-place using given arguments
}
}
Note that you don't need A's empty-parameter constructor anymore, so I have removed it.
i'm making a simple map with defined size as parameter, i would like it to be stored in my private member variable.
I will show a simple exemple :
class A {
public:
A (const int size) {
map_size_ = size;
//or | both will not compile
int map[size][size];
}
private:
int map_size_;
int map_[map_size_][map_size_];
}
I know the map_ won't compile, but i wonder how to declare it properly with a const int from the constructor parameter and without pointers.
You should use std::vector
#include <vector>
class A {
public:
explicit A (const int size) {
map_.resize(size);
for (auto &v : map_) v.resize(size);
}
private:
std::vector<std::vector<int>> map_;
};
This might not be the most optimal way from performance point of view, but it is the simplest one. There is no way around that. int[][] declarations do not work with non-compile time values in C++.
Tips:
Use explicit with single argument constructors.
You should use std::size_t instead of int for sizes.
This should work:
class A {
public:
A(int const size) {
_map_size = size;
_map = new int[_map_size * _map_size];
}
private:
int _map_size;
int* _map;
};
UPDATE - apparently people want a more comprehensive solution than the OP asked about.
class A {
public:
A(int const size)
: _map_size(size)
, _map(new int[_map_size * _map_size]) {
}
A(A const&) = delete;
~A() {
delete[] _map;
}
A& operator=(A const&) = delete;
int at(int x, int y) const {
if (x < 0 || x >= _map_size || y < 0 || y >= _map_size)
throw "That coordinate is in the giggleweeds";
return _map[y * _map_size + x];
}
int set_at(int x, int y, int value) {
if (x < 0 || x >= _map_size || y < 0 || y >= _map_size)
throw "That coordinate is in the giggleweeds";
_map[y * _map_size + x] = value;
}
private:
int _map_size;
int* _map;
};
I feel like this question must have been asked before but I couldn't find an answer from poking around on google. If it has please direct me to a link and I will remove this post.
Consider this minimal example that represents a larger problem I have. Say I created a simple "Point" and "Printer" class like so:
class Point {
public:
double x, y;
Point() {x = y = 0;}
Point(double x, double y) {
this->x = x; this->y = y;
}
};
template<typename T>
class Printer {
public:
T* mData;
int mSize;
// Constructor
Printer(std::vector<T> &input) {
mData = &input[0];
mSize = input.size();
}
// Simple Print function
void Print() {
printf(" - Showing %d items\n", mSize);
for (int i = 0; i < mSize; i++) {
const T &item = mData[i];
printf(" - Item %d: (%lf, %lf)\n", i, item.x, item.y);
}
}
};
I could use the printer class like this:
std::vector<Point> points; // fill the vector, and then...
Printer<Point> pointsPrinter(points); pointsPrinter.Print();
Now say someone else comes along and wants to use the Printer class with there own "Point" class declared like so:
class Pnt {
public:
double mX, mY;
// other stuff
};
If they try to do this:
vector<Pnt> pnts; // Fill the pnts, and then...
Printer<Pnt> pntsPrinter(pnts);
pntsPrinter.Print(); // COMPILE ERROR HERE!
Obviously this will fail because Pnt has no x or y members. Does there exist a way I can rewrite the Printer class to work with all generic user types? What I DONT want to do is copy a Pnt vector into a Points vector.
EDIT:
The only way I can think to make this work would be to pass in functions pointers. Something like this:
template<typename T>
class Printer {
public:
T* mData;
int mSize;
double* (*mXFunc) (T*);
double* (*mYFunc) (T*);
Printer(std::vector<T> &input,
double* (*xFunc) (T*),
double* (*yFunc) (T*))
{
mData = &input[0];
mSize = input.size();
mXFunc = xFunc;
mYFunc = yFunc;
}
void Print() {
printf(" - Showing %d items\n", mSize);
for (int i = 0; i < mSize; i++) {
T &item = mData[i];
printf(" - Item %d: (%lf, %lf)\n", i, *mXFunc(&item), *mYFunc(&item));
}
}
};
// Could then use it like so
inline double* getXPointVal(Point *point) {return &point->x;}
inline double* getYPointVal(Point *point) {return &point->y;}
inline double* getXPntVal(Pnt *point) {return &point->mX;}
inline double* getYPntVal(Pnt *point) {return &point->mY;}
Printer<Pnt> pntPrinter(pnts, getXPntVal, getYPntVal);
Printer<Point> pointsPrinter(points, getXPointVal, getYPointVal);
pntPrinter.Print();
pointsPrinter.Print();
The problem with this is that it looks ugly and also possibly introduces the function call overhead. But I guess the function call overhead would get compiled away? I was hoping a more elegant solution existed...
If you choose cout instead of printf to write your output, you can allow all printable types to define an overload for the << operator and use that generically inside Printer::print(). An overload could look like this:
std::ostream& operator<<(std::ostream &out, Point& p){
out << "Point(" << p.x << ", " << p.y << ")";
return out;
}
On a side note, I advise against storing a pointer to a vector's internal storage and size member. If the vector needs to reallocate, your pointer will be left dangling and invalid. Instead, you should pass the vector temporarily as a reference or keep a const reference.
You could define free (non-member) functions for each Point class you want to use. The advantage of this is that free functions can be defined later, without making changes to existing classes.
Example:
namespace A {
class Point {
public:
Point (int x, int y) : x_(x), y_(y) {}
int getX () const { return x_; }
int getY () const { return y_; }
private:
int x_, y_;
};
// in addition, we provide free functions
int getX (Point const & p) { return p.getX(); }
int getY (Point const & p) { return p.getY(); }
}
namespace B {
class Pnt {
public:
Pnt (int x, int y) : x_(x), y_(y) {}
int get_x () const { return x_; }
int get_y () const { return y_; }
private:
int x_, y_;
};
// Pnt does not have free functions, and suppose we
// do not want to add anything in namespace B
}
namespace PointHelpers {
// free functions for Pnt
int getX (Pnt const & p) { return p.get_x (); }
int getY (Pnt const & p) { return p.get_y (); }
}
// now we can write
template <class PointTy>
void printPoint (PointTy const & p) {
using PointHelpers::getX;
using PointHelpers::getY;
std::cout << getX (p) << "/" << getY (p) << std::endl;
}
A::Point p1 (2,3);
B::Pnt p2 (4,5);
printPoint (p1);
printPoint (p2);
If the free functions live in the same namespace as the corresponding class, they will be found by argument-dependent name lookup. If you do not want to add anything in that namespace, create a helper namespace and add the free functions there. Then bring them into scope by using declarations.
This approach is similar to what the STL does for begin and end, for instance.
Don't expect from the templates to know which members of given class/structure corresponds to your x and y...
If you want to create generic solution you could tell your printer function how to interpret given object as your Point class using e.g. lambda expression (c++11 solution):
#include <iostream>
class Point {
public:
double x, y;
Point() {x = y = 0;}
Point(double x, double y) {
this->x = x; this->y = y;
}
};
class Pnt {
public:
double mX, mY;
// other stuff
};
template <class P, class L>
void Print(const P &p, L l) {
Print(l(p));
}
void Print(const Point &p) {
std::cout << p.x << ", " << p.y << std::endl;
}
int main() {
Print(Point(1, 2));
Print(Pnt{4, 5}, [](const Pnt &p) -> Point {return Point(p.mX, p.mY);});
}
So, I have an algorithm that takes a few sensors, scales them to a temperature and puts the temps in a global data store. However, sensor class A does more calculations that Class B needs. I can't put the new calcs in the data store, and i don't want to include class A inside class B just to get one piece of data with a getter.
Class A
{
private:
float x[4];
float y[4];
public:
//Scaling functions, etc...
}
Class B
{
private:
float c[4];
public:
//Scaling functions etc...
}
What would be the best way to get x[4] passed to class B to put in c[4]? The real classes have much more going on, this is about as simple as I think I can make. x[4] has data that needs to be used in class B.
class A
{
private:
float x[4];
float y[4];
public:
float* getXs()
{
return x;
}
}
class B
{
private:
float c[4];
public:
//Scaling functions etc...
void setXs(float *x)
{
for (int i=0;i<4;i++)
c[i] = x[i];
}
}
Well, you could use friends, if you're not willing to write accessors:
http://en.wikipedia.org/wiki/Friend_class
Some would argue this breaks encapsulation, and that a getter would be the preferred approach.
Use a getter of x[4] on an instance of A when calling the constructor of B.
#include <string.h>
class A
{
private:
float x[4];
float y[4];
public:
float const *xArray() const
{
return x;
}
};
class B
{
private:
float c[4];
public:
void setCArray(float const arr[4])
{
memcpy(c, arr, 4 * sizeof(int));
}
};
int main()
{
A a;
B b;
b.setCArray(a.xArray());
}
There are number of ways. The best depends on Your criteria.
If time is not crucial for you I would be simple and use copy constructor:
Class A
{
private:
float x[4];
float y[4];
public:
const float& X(int i) { return x[i]; }
}
Class B
{
private:
float c[4];
public:
B( const A& a ) {
for( k = 0; k < 4; k++ )
c[k] = a.X(k);
}
}
If time is crucial you can consider to use pointers copy. But be Very accurate with it:
Class A
{
private:
friend B;
float x[4];
float y[4];
public:
...
}
Class B
{
private:
const float* const c;
public:
B( const A& a ):c(a.x){}
// use c like c[4], but don't change it.
}
I am making my first steps in learning OOP . And here is the first problem which I can't solve.
The max function in this class should return the maximum of two numbers . I want to keep the numbers in the private scope and the functions in the public scope . But when I want to use variables from struct data{} in the public scope the compiler says that the variables are not declared . Please tell me why I get these errors .
class myclass{
private:
struct data{
int q ;
int w;
};
public:
void get(int a, int b){
struct data = {a , b}; // here I want to pass the variables to data struct
}
int max (){ // this function returns the biggest number
if(q>w)
return q;
else
return w;
}
};
struct data{
int q ;
int w;
};
only declares a type, not an object, so there are no q and w members anywhere inside your class instances. You need the declare an instance of the struct:
struct {
int q;
int w;
} data;
Then, you can write max as:
int max()
{
if (data.q > data.w)
return data.q;
else
return data.w;
}
(I've no idea what your get method is supposed to do, so I have no replacement for that.)
In C++ "class" and "struct" are close to being synonymous (the same thing). The ONLY difference is that a "struct" defaults to being "public" accessibility while a "class" defaults to private.
Once you understand this, it should become obvious that what you are doing is defining a sub-type within your class.
class myclass {
private: // <- not required, you already said that by saying "class".
struct data {
// <-- this is a class definition with "public:" just here.
...
};
};
C++ allows you to nest class/structure definitions so that you can, for example, create structures that marshal parameters or return values.
class Database {
class Result { ... };
};
...
class Exam {
class Result { ... };
};
These two result classes avoid namespace collision, by being Database::Result and Exam::Result instead of just "Result".
However - these are only definitions. They do not - as shown - have any effect on the outlying class, that is: they aren't being used to add a member to the class.
Your code:
class myclass{
private:
struct data{ // <-- this is a TYPE declaration, struct myclass::data
int q ; //
int w; //
}; // <-- no member name here so does not affect myclass itself.
public:
void get(int a, int b){
struct data = {a , b}; // here I want to pass the variables to data struct
}
int max (){ // this function returns the biggest number
if(q>w)
return q;
else
return w;
}
};
Declares a type "myclass::data" but does not add a member of type "myclass::data" to the class. The line "struct data = " is illegal, you're trying to assign values to a TYPE.
It should probably be written as
class MyClass {
int m_q;
int m_w;
public:
void set(int q, int w) {
m_q = q;
m_w = w;
}
int max() const {
return (m_q > m_w) ? m_q : m_w;
// or #include <algorithm> and return std::max(m_q, m_w);
}
};
You only need to hoist q & w into a struct if you are going to reuse that structural definition outside the confines of the class, e.g. in derived or parallel classes where you may want to add more of the same type of thing, in which case, you could perhaps do the following, but if you do it this exact way you'll eventually kick yourself for breaking encapsulation:
class MyClass {
public:
struct Data {
int m_q;
int m_w;
};
private:
Data m_data;
void set(int q, int w) {
m_data.m_q = q;
m_data.m_w = w;
}
int max() const {
return (m_data.m_q > m_data.m_w) ? m_data.m_q : m_data.m_w;
}
};
A better way, if this coupling of members needs to be externally visible to some degree would be:
class MyClass {
public:
class Data {
int m_q;
int m_w;
public:
Data() : m_q(0), m_w(0) {}
Data(int q, int w) : m_q(0), m_w(0) {}
void set(int q, int w) {
m_q = w;
m_w = w;
}
int q() const { return m_q; }
int w() const { return m_w; }
int max() const { return (m_q > m_w) ? m_q : m_w;
};
private:
Data m_data;
public:
MyClass() : m_data() {} // or = default
MyClass(int q, int w) : m_data(q, w) {}
MyClass(const Data& data) : m_data(data) {}
// Read-only access
const Data& data() const { return m_data; }
// To allow write access, e.g. for set:
Data& data() { return m_data; }
};
It's kinda overkill for such a simple case, but welcome to C++: the boilerplate language.
You have defined the structure but there is no object of that type. You should declare an object and you will not get any error.
class myclass{
private:
struct data{
int q ;
int w;
}var;
public:
void get(int a, int b){
var .q= a;
var.w=b; // here I want to pass the variables to data struct
}
int max (){ // this function returns the biggest number
if(var.q>var.w)
return var.q;
else
return var.w;
}
};