My question might be a bit confusing because I really did not know how to word it. Essentially, I have three classes in total and two of them are holding double pointers of a type defined in the third class.
class Wheel
{
unsigned m_orderID{};
std::string m_name{};
};
The other two classes - Car
& Truck
- have identical private members:
class Car{
const Wheel** m_ptrToArray{};
size_t m_count{};
};
My problem is that, in main()
, I am making changes to the Wheel
class values, where the Truck
needs to have values that change, but the Car
class needs to remain unchanged. Because the Car
and Truck
are both using double pointers, any update to the Wheel
values changes the output for both because they are accessing the information via address, if I'm understanding correctly.
I believe my problem lies in the constructor used to create a Car
object:
Car::Car(const Wheel* wheels[], size_t count)
I am trying to make a copy of the Wheel
array that's passed in, so that I can assign the copy to the Wheel** m_ptrToArray
member. That way, if I update the original array in main()
, only Truck
will change and Car
will remain untouched. But I can't figure out how to do it.
If I use the following code in my constructor:
m_ptrToArray = new const Wheel*[m_count];
for (auto i = 0u; i < m_count; i++)
{
m_ptrToArray[i] = wheels[i];
}
It doesn't do what I want, because I'm just assigning the address of the wheels
array.
If I do:
Wheel* temp = new Wheel[m_count];
for (auto i = 0u; i < m_count; i++)
{
temp[i] = *wheels[i];
}
m_ptrToArray = new const Wheel*[m_count];
for (auto i = 0u; i < m_count; i++)
{
m_ptrToArray[i] = &temp[i];
}
It works correctly, changing Truck
but not Car
. However, I run into memory loss because I'm using the new
keyword without delete
- because I have no idea how to pass it other than &temp[i]
which means if I delete
it, it won't be able to reach the value any more.
I am at a loss. Hopefully, this explanation makes sense to somebody who knows what they are doing. Let me know if you need any more information at all!
You are on the right track. Truck
can just save the Wheel*
pointers it is given, while Car
can make its own copy of the Wheel
objects. Simply destroy those copies in Car
's destructor. That seems to be the piece you are missing. Simply store the extra objects as an additional member of the Car
class, instead of using a local variable in the constructor.
Try something like the following (FYI, I'm ignoring the need for copy/move constructors and assignment operators, per the Rule of 3/5/0. I'll leave that as an exercise for you to implement).
For Car
:
class Car{
const Wheel** m_ptrToArray{};
size_t m_count{};
Wheel* m_wheels{};
public:
Car(const Wheel* wheels[], size_t count);
~Car();
};
...
Car::Car(const Wheel* wheels[], size_t count)
{
m_count = count;
m_wheels = new Wheel[count];
m_ptrToArray = new const Wheel*[count];
for (auto i = 0u; i < count; ++i)
{
m_wheels[i] = *(wheels[i]);
m_ptrToArray[i] = &m_wheels[i];
}
}
Car::~Car()
{
delete[] m_ptrToArray;
delete[] m_wheels;
}
Or simpler:
class Car{
const Wheel** m_ptrToArray{};
size_t m_count{};
public:
Car(const Wheel* wheels[], size_t count);
~Car();
};
...
Car::Car(const Wheel* wheels[], size_t count)
{
m_count = count;
m_ptrToArray = new const Wheel*[count];
for (auto i = 0u; i < count; ++i)
{
m_ptrToArray[i] = new Wheel(*(wheels[i]));
}
}
Car::~Car()
{
for (auto i = 0u; i < m_count; ++i)
{
delete m_ptrToArray[i];
}
delete[] m_ptrToArray;
}
And for Truck
:
class Truck{
const Wheel** m_ptrToArray{};
size_t m_count{};
public:
Truck(const Wheel* wheels[], size_t count);
~Truck();
};
...
Truck::Truck(const Wheel* wheels[], size_t count)
{
m_count = count;
m_ptrToArray = new const Wheel*[count];
for (auto i = 0u; i < count; ++i)
{
m_ptrToArray[i] = wheels[i];
}
}
Truck::~Truck()
{
delete[] m_ptrToArray;
}