C++ creating a copy constructor for a class with a reference member variable
Asked Answered
V

1

10

I have a class ModelRecorder with contains a reference modelRef_ to another class OpModel.

class ModelRecorder : public CompositionalModel //This is an abstract base class
{

    OpModel& modelRef_;
};

When an instance of ModelRecorder is created and modelRef_ is initalized. Thats fine I unerstand that.

How would I write a copy constructor for ModelRecorder so that if another instance is created, the reference memeber modelRef_ will be initalized with the previous created OpModel object?

Note that CompositionalModel is an abstract base class.

In another class there is fucntion that returns a reference to CompositionalModel he base class. I understand returning the narrower base class is a good OOP.

For example CompositionalModel& recordedModel();

I want to pass this reference to the base class to the copy constructor.

I tried this but it gives the error, which is correct modelRef is in the dereived class ModelRecorder.

error: ‘const class mv::CompositionalModel’ has no member named ‘modelRef_

mv::ModelRecorder::ModelRecorder(const CompositionalModel& arg) : CompositionalModel{static_cast<const ModelRecorder&>(arg)}, modelRef_{arg.modelRef_}
{
}
Vizor answered 23/8, 2018 at 10:6 Comment(2)
This is what does the default copy constructor for references. Nothing to do. Unless there's something fishy about what you mean by the reference memeber modelRef will be initalized with the previous created OpModel object_. minimal reproducible example please.Holt
ModelRecorder(const ModelRecorder&) = default will do itAmberambergris
A
10

There are 2 ways:

The first way - make compiler do it for you:

ModelRecorder(const ModelRecorder&) = default;

The second way - implement it yourself:

ModelRecorder(const ModelRecorder& arg)
    :CompositionalModel{arg}, modelRef_{arg.modelRef_} {}

Note that you have to use the member initializer list, since we're dealing with references. The difference between the above code and this:

ModelRecorder(const ModelRecorder& arg) 
    :CompositionalModel{arg} {
    modelRef_ = arg.modelRef_;
}

is that the later does not initialize the reference. It violates the rules, since references must be initialized, not assigned later. My best advice is to stick with the easy way, since it's the least possible to mess up using it

Amberambergris answered 23/8, 2018 at 10:15 Comment(8)
The second and third version do not call the base class copy constructor, you want to add this. See Item 12 ("Copy all parts of an object") in Effective C++, 3rd edition.Forestall
My bad, overlooked the fact ModelRecorder inherits from CompositionalModel. Thank you for pointing that out, sir.Amberambergris
You're welcome, it's always rewarding and fun to throw Scott Meyers items at users :PForestall
@Amberambergris thank you - what if you wanted to pass a reference to a base class CompositionalModel to the copy constructor? A different part of the program returns a reference to CompositionalModel. I understand returning a reference to the narrower base class is good OOP.Vizor
@pelicanbrady Then it's not longer a copy constructor. Regardless, a minimal reproducible example of your situation would really help in providing good answers.Etching
@Max Langhof ah I thought so. The program is quite large but I have amended my question to include as much details as possible. I sorry for causing confusion I thought I required a copy constructor.Vizor
@pelicanbrady This is a pretty different question now (and runs into its own issue that I would like to detail). It also still does not show the relation between OpModel and the other two models. Would you mind asking a new question instead, so that this question+answer are not invalidated?Etching
@Max Langhof - sure no problem.Vizor

© 2022 - 2024 — McMap. All rights reserved.