C++: Dynamic memory allocation and class constructors - c++

I believe that I may be either misusing OOP or doing something wrong with my memory allocation in class constructors.
I will illustrate what I am doing with a simplified example:
class data
{
data(int n) : m_data(new double[n])
{
}
virtual ~data()
{
delete [] m_data;
}
double min() { ... }
double max();
double mean(); // return minimum, maximum and mean values
double *m_data;
}
class dual_data : public data
{
dual_data(int n) : m_data(new double[2*n])
{
}
}
I believe this will cause a disastrous memory leak. (It should be clear why, as one constructor allocates memory before the other then overwrites the pointer with another call to new.)
In case it isn't already clear, I have 2 classes: One is a class similar to std::vector which handles data storage in memory for me, and the other is a derived class which does the same thing, but expects data in the format of x,y pairs rather than individual values. The reason for this is that x,y pairs can be processed in different ways than to just a vector. For example, with statistical data processing to compute correlations or something else entirely. But it is still useful to be able to call the functions min(), max() and mean() in the class dual_data, which are inherited from data.
What should I do to correct for the memory leak?

Maybe this should do: you tell the base class to allocate an array of 2*n elements. Besides the base class is responsible for freeing the memory. No destructor needed.
class dual_data : public data
{
dual_data(int n) : data(2*n)
{
}
}

Since data already has an array of doubles, instead of trying to muck with that, just make another parallel array of doubles in dual_data.
class data
{
public:
data(int n) : m_data(new double[n])
{
}
virtual ~data()
{
delete [] m_data;
}
double *m_data;
}
class dual_data : public data
{
public:
dual_data(int n) : data(n), d_data(n)
{
}
virtual ~dual_data() {
delete[] d_data;
}
double* d_data;
}
Now, your dual_data class has the original m_data array, plus an additional d_data array of the same length, whose elements are to be used for the second element in the pair. For example, the zeroth pair would be (m_data[0], d_data[0]).

You cannot initialize a variable of your parent class. It will not compile.
You can have the memory leak if you do inside the constructor.
class dual_data : public data
{
public:
dual_data(int n) : data(n)
{
m_data = new double[2*n];
}
};
However, it is your responsability do it well. A great powder is a great responsibility.
You have it doing this:
class dual_data : public data
{
public:
dual_data(int n) : data(2*n) {}
};
A better solution is not use inheritance. It is allways better Composititon over inheritance.
#include "data.h"
class dual_data {
public:
dual_data( int n ) : data_1(n), data_2(n) {}
private:
data data_1;
data data_2;
};
Better using interfaces:
class CdataIf
{
public:
virtual ~CDataIf() = 0;
virtual double min() = 0;
virtual double max() = 0;
virtual double mean() = 0;
};
class data : public CdataIf { ... };
class data_dual : public CdataIf { ... };

First, implement a basic vector class (or use directly std::vector<double> if possible)
class vector_of_double
{
public:
explicit vector_of_double(std::size_t mSize) :
mValues(new double[size]{}),
mSize(size)
{}
~vector_of_double() { delete[] mValues; }
// implement these if required
// deleted for now to Respect rule of 3(5) as default implementation is incorrect.
vector_of_double(const vector_of_double&) = delete;
vector_of_double& operator = (const vector_of_double&) = delete;
vector_of_double(const vector_of_double&&) = delete;
vector_of_double& operator = (const vector_of_double&&) = delete;
std::size_t size() const { return mSize; }
// Implement required missing stuff if required as push_back, resize, empty, clear
// introduction of mCapacity may be required.
double operator[] (std::size_t index) const { return mValues[index]; }
double& operator[] (std::size_t index) { return mValues[index]; }
// To be able to use for range and iterator style
const double* begin() const { return mValues; }
const double* end() const { return mValues + mSize; }
double* begin() { return mValues; }
double* end() { return mValues + mSize; }
private:
double* values;
std::size_t size;
};
then you may implement your classes (without worry about memory management):
class data
{
public:
explicit data(int n) : m_data(n) {}
// Or use your own implementation
// TODO: Handle case with empty vector
double min() const { return *std::min_element(m_data.begin(), m_data.end()); }
double max() const { return *std::max_element(m_data.begin(), m_data.end()); }
double mean() const {return std::accumulate(m_data.begin(), m_data.end(), 0.) / m_data.size();}
private:
vector_of_double m_data;
};
And
class dual_data
{
public:
explicit dual_data(int n) : m_data1(n), m_data2(n) {}
// your functions as
std::pair<double, double> means() double {return {m_data1.means(), m_data2.means()};}
private:
data m_data1;
data m_data2;
};

I would approach this differently, instead declare an interface containing the min,max and mean. Then create the classes that implement the interface but with different underlying structures.
struct ICommon
{
virtual double min() = 0;
virtual double max() = 0;
virtual double mean() = 0;
};
class Data : public ICommon
{...};
class DualData : public ICommon
{...};

Related

Cannot implement base class with virtual getters that are defined in child classes

I have a class that is called Object, this class's header is:
class DLL_SPEC Object {
public:
Object();
virtual ~Object();
virtual std::string getString() const;
virtual void setString(std::string value);
virtual int getInt() const;
virtual void setInt(int value);
virtual double getDouble() const;
virtual void setDouble(double value);
virtual bool isType(FieldType type) const;
};
And my child classes are as follows:
class DLL_SPEC IntObject : public Object {
public:
IntObject() : value(0) {}
IntObject(int v) : value(v) {}
void setInt(int value) override { this->value = value; };
int getInt() const override { return this->value; };
bool isType(FieldType type) const override;
private:
int value;
};
class DLL_SPEC DoubleObject : public Object {
public:
DoubleObject() : value(0.0) {}
DoubleObject(double v) : value(v) {}
void setDouble(double value) override { this->value = value; };
double getDouble() const override { return this->value; };
bool isType(FieldType type) const override;
private:
double value;
};
class DLL_SPEC StringObject : public Object {
public:
StringObject() : value("") {}
StringObject(std::string v) : value(v) {}
void setString(std::string value) override { this->value = value; };
std::string getString() const override { return value; };
bool isType(FieldType type) const override;
private:
std::string value;
};
Now, the problem is, I have an array of Objects and I want to get a string representation of a StringObject.
I call array[0].getString() and even though the object is of type StringObject, the method that gets called is the one is the base class, which I understand.
So, how would I go about implementing that whenever I call getString() on the base class it goes to the child one of the SAME object?
I've tried using this method:
std::string Object::getString() const
{
return dynamic_cast<StringObject*>(this).getString();
}
but then I get an error stating I cannot cast away const or any type qualifier, which is fixed by deleting const modifier (which I MUST leave there as it's according to the task), but then I get another one stating that no suitable constructor exists. So how would I go about implementing this and getting this base class to use the one of the child one?
EDIT: Added a small example that goes into the getString method of Object class and not the StringObject class.
int findPersonId(std::string whereName)
{
Db* db = Db::open("database");
Table* people = db->openTable("table");
auto iteratorTable = table->select();
while (iteratorTable->moveNext())
{
for (size_t i = 0; i < table->getFieldCount(); i++)
{
if (table->getFields()[i]->getName() == "id")
{ //this one beneath goes to the base class and not StringObject
std::string foundRow = iteratorPeople->getRow()[i]->getString();
if (foundRow == whereName)
{
return iteratorTable->getRowId();
}
}
}
}
return 0;
}
Note: The Table* is 2D array that consists of Object** (array that contains StringObject, IntObject, DoubleObject). The method .getRow() return the Object** array that consists of StringObject ...
The way I initiate the objects that go into the array is
Table* table= db->openOrCreateTable("table", 2, userFields); //this creates a 2d array
StringObject* name = new StringObject("Joseph");
IntObject* id = new IntObject(5);
Object** row = combineToRow(id, name);
table->insert(row); //insert an array into 2D array
The method combineToRow is just a simple convertor to Object**.
template<typename A, typename B>
Object** combineToRow(A a, B b) {
return new Object * [2]{ a, b };
}
You have not implemented a getString method for your IntObject, and since you didn't override it you are calling the base method. Once you implement it like this
class IntObject : public Object {
...
virtual std::string getString() const { return std::to_string(value); };
...
};
then you can call it.
int main(){
StringObject* name = new StringObject("Joseph");
IntObject* id = new IntObject(5);
Object** row = combineToRow(id, name);
std::cout << row[0]->getString() << " " << row[1]->getString();
}
5 Joseph
See working version here

How to add derived class objects to an array of base class type?

unfortunately, I can't use std::vector and have to use plain C++ arrays. I got the following code:
class Base
{
}
class DerivedCar : Base
{
public:
DerivedCar(int a) a(a) {};
private:
int a;
}
class DerivedHouse : Base
{
public:
DerivedHouse(float b) b(b) {};
private:
float b;
}
class Vector
{
Vector() :
index(0)
void add(const DerivedCar& car)
{
vec[index] = new DerivedCar(car.a);
index++;
}
void add(const DerivedHouse& house)
{
vec[index] = new DerivedHouse(house.b);
index++;
}
private:
Vector vec[100];
int index;
}
int main()
{
Vector vector;
DerivedCar car(100);
DerivedHouse house(2.f);
vector.add(car);
vector.add(house);
}
I would like to have an array of type Base and add objects of a derived type.
Is there a better approach to this other than the way I did? What would be the best way to keep copying of objects at a minimum.
How to add derived class objects to an array of base class type?
You can not put derived class objects into raw array or std::vector of base class because the derived class objects are usually larger and so simply do not fit there.
Is there a better approach to this other than the way I did?
Better approaches are certainly out there. One good example of such containers with polymorphic elements is boost::base_collection. Read its documentation and its source code. If you do not understand some detail in it then ask about that detail in Stack Overflow.
What would be the best way to keep copying of objects at a minimum.
Containers that only contain pointers to objects and intrusive containers
keep copying of objects at minimum. However such containers do not
manage the objects and so responsibility of objects life time has
to be taken by something outside.
Here is a possible way that implements a linked list:
class Base
{
};
class DerivedCar : public Base
{
public:
DerivedCar(int a) { _a = a; };
private:
int _a;
};
class DerivedHouse : public Base
{
public:
DerivedHouse(float b) { _b = b; };
private:
float _b;
};
class Object
{
public:
const Base *data;
const Object *next;
};
class Vector
{
public:
void add(const Base& v)
{
Object item;
item.data = &v;
head.next = &item;
index++;
}
private:
Object head;
int index = 0;
};
int main()
{
Vector vector;
DerivedCar car(100);
DerivedHouse house(2.f);
vector.add(car);
vector.add(house);
}

How I set a reference after constructor?

I want to set a reference after constructor
Example:
class OtherClass
{
public:
OtherClass() : m_class(Class()){}
inline void SetData(int data1, int data2)
{
//calculate data3
// I tried:
m_class = Class(data3);
//but it doesn't worked
}
protected:
private:
Class& m_class;
};
Edit:
The Exception is: vector subscript out of range
because I have glm vectors in the Class.
I need also call functions in my Class.
Edit 2:
Why I need this?
Because I have an other class [ExClass] which extends and which have to calulate in constructor:
ExClass::ExClass(float d1, float d2, ...) {
//calculate data from given values
SetData(data);
}
The proper way to do that is to use a pointer and not a reference, as opposed to references - pointers can be set after object creation. Note also that referring (or pointing) to a local variable whose lifetime will end, while still in use, is a bad idea.
Your code may be changed to use a pointer and dynamic allocation or alternatively, std::unique_ptr. There are of course other options, these are just examples.
Option 1 - a pointer and dynamic allocation
class OtherClass
{
public:
OtherClass() : m_class(nullptr){}
~OtherClass() {
delete m_class;
}
// block copy and assignment (or implement them)
OtherClass(const OtherClass&) = delete;
OtherClass& operator=(const OtherClass&) = delete;
void setData(int data1, int data2)
{
// ... calculate data3 ...
m_class = new Class(data3);
}
bool hasInnerObj() const {
return m_class; // or: return m_class != nullptr;
}
/** call this function only if hasInnerObj() returned true */
Class& getInnerObj() {
return *m_class;
}
private:
Class* m_class;
};
Option 2 - std::unique_ptr
class OtherClass
{
public:
void setData(int data1, int data2)
{
// ... calculate data3 ...
m_class = std::make_unique<Class>(data3);
}
bool hasInnerObj() const {
return m_class; // or: return m_class != nullptr;
}
/** call this function only if hasInnerObj() returned true */
Class& getInnerObj() {
return *m_class;
}
private:
std::unique_ptr<Class> m_class;
};
You have two problems:
Reference class members (i.e. m_class) need to be initialized when object is created.
However, both your Class instances (one in the constructor, and one in SetData) are put on the stack and popped right away, making the reference invalid.
What you need to do is make sure that your class object actually lives through the function call. One way of achieving that is allocating it prior to passing it to the OtherClass constructor or SetData function:
class Class {};
class OtherClass
{
public:
OtherClass(Class& c) : m_class(c){}
inline void SetData(Class& c)
{
m_class = c;
}
protected:
private:
Class& m_class;
};
int main()
{
Class a;
OtherClass c(a);
Class b;
c.SetData(b); // changes m_class
return 0;
}
Live example here.

I have different classes and I want to make a vector with objects from those classes and sort it by a value

I have the first class.
class Class1
{
public:
Class1();
double getVal();
bool operator<(Class1& A) { return getVal() > A.getVal(); }
virtual ~Class1();
}
And from this class I derive two classes.
class Class2 : virtual public Class1
{
protected:
int val1;
public:
int getVal(){ return val; }
bool operator<(Class1& A) { return getVal() > A.getVal(); }
}
And the second class.
class Class3 : virtual public Class1
{
protected:
double val2;
public:
double getVal(){ return val; }
bool operator<(Class1& A) { return getVal() > A.getVal(); }
}
And finally from these classes I derive one class.
class Class4 : public Class2, public Class3
{
protected:
char* info;
public:
double getVal(){ return val1+val2; }
bool operator<(Class1& A) { return getVal() > A.getVal(); }
}
And in main I have:
void main(){
vector<Class1*> vec;
vec.push_back(new Class2(3));
vec.push_back(new Class3(5));
vec.push_back(new Class4(2));
sort(vec.begin(),vec.end());
}
The code is pushing back objects in the vector just fine, but when I'm trying to sort it nothing happens.
I suspect that is something wrong with the parent class (Class1) and mainly the getVal() method, but I don't know what to do.
The question is: How can I sort this vector?
The problem here is that you have a vector of pointers. Therefore the comparison done by std::sort is done using the pointers and not the structures pointed to by them.
For it to work, you have to either provide a global operator< function which takes two pointers as arguments. Or you provide a comparison function as a third argument to std::sort. Both needs to dereference the pointers.
Also, you still need to mark your functions as virtual for polymorphism to work.

Does C++ support abstract array lengths

If I have a base class A I would like to be able to write code in Athat uses an array whose size is determined by its children
I want to be able to have an array of pointers to A, but I don't want to have a separate member function created for each length
The best I could come up with is as follows:
class A
{
char type;
int * values;
int calc(int pos); // implementation is not relevant to question
public:
A (int * arr) : values(arr) {}
int foo(int pos)
{
int index=calc(pos);
return values[index];
}
};
template <size_t X>
class B : public A
{
int vals[X];
public:
B() : A(vals) {}
};
template<>
class B<0>; // don't want 0 allowed
This allows A to access an array where the child determines the size, and it is contiguous memory
But, it wastes the space of the values pointer and obfuscates information the compiler could use for optimization since as implemented it doesn't have to be contiguous memory that the child passes on construction, but I would like to require continuous memory.
Ideally I would like to use the offset directly in A
In C this works as int values[] but there is no C++ equivalent
Yes you can, using templates:
template<std::size_t size>
struct A {
A(std::array<int, size> _values) : values{_values} {}
private:
std::array<int, size> values;
};
struct B : A<4> {
using A<4>::A;
};
Then, you can use your class like this:
B myB{5, 6, 3, 2};
std::array allocates memory on the stack, or in the struct directly, just like a fixed array. You can test this by comparing sizes.
If you need a common base class, you can do this:
struct C {
virtual ~C() {}
virtual int* data();
virtual std::size_t size();
};
And then overriting theses in A:
template<std::size_t size>
struct A : C {
A(std::array<int, size> _values) : values{_values} {}
int* data() override {
return values.data();
}
std::size_t size() override {
return size;
}
private:
std::array<int, size> values;
};
The classic way to implement this is using inheritance and virtual members:
class A {
virtual int& value_at(size_t pos);
// other interesting methods
};
// subclass of A that uses std::vector for storage
class B: public A {
std::vector<int> storage;
int& value_at(size_t pos) {
return storage[pos];
}
};
// subclass of A that uses a fixed-size array for storage
template<int N>
class C: public A {
int storage[N];
int& value_at(size_t pos) {
return storage[pos];
}
};
B b; // ...initialize b...
C<10> c; // ...initialize c...
A *a1 = &b;
A *a2 = &c;
// call a1->value_at(), a2->value_at() to access arrays
// transparently, regardless of storage (along with other
// public methods of A).
This approach will require A::value_at to dispatch via a virtual table or equivalent mechanism. If it is known at compile-time which storage strategy will be used, you can make A a template class:
template<typename T>
class A: public T {
// other interesting methods, that use value_at() from T
};
class vec_storage {
std::vector<int> storage;
public:
int& value_at(size_t pos) {
return storage[pos];
}
};
// subclass of A that uses a fixed-size array for storage
template<int N>
class array_storage {
int storage[N];
public:
int& value_at(size_t pos) {
return storage[pos];
}
};
A<vec_storage> b;
A<array_storage<10>> c;
In this example, b and c will perform without the additional indirection at run-time, but at the cost that there is no generic base class, so a function expecting some A & cannot be passed a reference to either b or c.
For just the basic ability to change the size of the object's array, you're probably looking for templates, as Fred Larson pointed out. It's actually quite simple...
template <const int arraySize>
class MyClass
{
private:
int vals[arraySize];
}
At this point, you don't even need any derived classes. You're good to go, and can work with any size on the fly.
Bear in mind, however, that MyClass is not a valid type in this scenario. Because this is a template, you must specify the size.
MyClass wrong; //This will throw an error. MyClass is not a type.
MyClass<64> right; //This is a proper use of the type.
If you need the additional ability to store those objects of different sizes, you can combine this with inheritance fairly easily using a virtual [but not abstract] base class.
(Please ignore the crufty design, as I haven't bothered to define my constructors/destructors in this example.)
class BaseClass
{
public:
BaseClass(){}
virtual int access(int i)
{
return 0;
}
virtual ~BaseClass(){}
};
template <const int arraySize>
class MyClass : public BaseClass
{
public:
MyClass(){}
int access(int i)
{
return vals[i];
}
~MyClass(){}
private:
int vals[arraySize];
};
WARNING: It is critical that the base NOT be abstract if you want to be able to store your derived classes in a vector. See this question.
In this example, of course, you may want to create wrapper functions for accessing the array.