On Saturday I have an exam and I'm going through the past papers and I've encountered question according to C++ code:
class Car {
char *LicencePlate;
int age;
public:
Car(const Car &); //this declaration
~Car();
}
What is the purpose of the declaration on line 5? In general what functionality should the implementation of a declaration of this nature provide? Write the code required for the implementation of the declaration on line 5 as it would appear in the Car.cpp
file given the information provided.
It initializes members before the body of the constructor executes. Save this answer. Show activity on this post. It's called an initialization list.
In C++, the colon ':' operator, to my understanding, is used for inheritance. However, inside classes, I have seen it used presumably for other reasons. What is this operator used for? - Open in App. In C++, the colon ":" operator, to my understanding, is used for inheritance.
It is a copy constructor, it's purpose is to make an exact copy of the object which was given as a parameter.
I will leave it to you to decide how best to do that.
Let's go through this.
As you can tell from the name, that's a constructor. Because it takes a parameter a reference to an object of the same type, it's a copy constructor (C++ nomenclature).
As you know (or not), if you don't have a copy constructor, the compiler will generate one for you. The compiler generated copy constructor does a shallow copy.
class Car {
char *LicencePlate;
public:
Car(char* plate, int size)
{
LicencePlate = new char[size];
strcpy(LicencePlate, plate);
}
~Car()
{
delete[] LicencePlate;
}
};
I've modified your class a bit to better explain. Your class manages memory now. It allocates memory for LicencePlate
. This is the scenario where you don't have a copy constructor. Say you do:
Car a("abc",3);
The compiler generated copy constructor is called with:
Car b(a);
But remember, this only does a shallow copy. So, actually, a.LicencePlate == b.LicencePlate
. Can you see anything wrong with that?
When a
goes out of scope, the destructor is called, and a.LicencePlate
is deleted. But then you run into undefined behavior when b
goes out of scope, because b
's destructor will try to delete the same memory (remember, the two pointer point to the same memory because a shallow copy was created).
To avoid this, you define your own copy constructor:
class Car {
char *LicencePlate;
int sz;
public:
Car(char* plate, int size)
{
LicencePlate = new char[size+1]();
strcpy(LicencePlate, plate);
sz = size;
}
Car(const Car& other)
{
LicencePlate = new char[other.sz+1]();
sz = other.sz;
strcpy(LicencePlate, other.LicencePlate);
}
~Car()
{
delete[] LicencePlate;
}
};
The rule of three means you should implement an assignment operator (you already have a copy constructor and a destructor). The motivation behind this is the same, only the problem replicates when you assign instead of initialize:
Car a("abc",3);
Car b;
b = a; //assignment - operator= is called
Now we're safe. b
, when copied, will allocate new memory to hold the licence plate, so the double-delete can't occur.
I changed the code to demonstrate the point but you'll still have to put logic in there yourself.
That's a copy constructor declaration. It takes a reference to a constant Car
, meaning you can read the passed in value, but can not (without dodgy casts) write it. This is just the canonical way of creating a new object by copying the original. You will probably want to do a strdup
as part of the implementation.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With