This actually doesn't have anything to do with pointers or references. You've got the wrong syntax for calling the constructor of the member object _digipot
, and your code gets parsed as something different that results in a confusing error message.
You have a class Cell
which has a member _digipot
that is of type class DS3904
. So your constructor for Cell
needs to construct _digipot
, but in C++, this isn't done by calling _digipot
's constructor in the body of your Cell
constructor. Instead it needs to be done in a member initializer list. So the correct way to write your constructor Cell::Cell
would be:
Cell::Cell(int cellNumber, int digipotAddress, int resistorAddress)
: _digipot(digipotAddress, 2),
_cellNo(cellNumber),
_resistorAddress(resistorAddress)
{
// no code needed in the body
}
The idea is that in C++, there should never be any point in the program where you can see an object that exists but has not been fully constructed, with the one exception being that object's own constructor. If it was up to the body code of Cell::Cell
to call _digipot
's constructor, then it could also try to access _digipot
before calling the constructor, at which point it would find it in an unconstructed state. So _digipot
has to be constructed before the body of Cell::Cell
starts execution, yet there still needs to be a way to specify which constructor of _digipot
should be called, and with what arguments. Member initializer lists were invented to achieve this.
(You don't technically have to include the int
members _cellNo
and _resistorAddress
in the member initializer list: if you leave them out, they get initialized to indeterminate values, and you can then assign to them in the body of the constructor like your existing code does. But it's cleaner to do everything in the member initializer list.)
So where did the weird error message come from? There are actually two error messages for your code, of which you only posted the second one, and the first one is the more informative one:
Cell-old.cpp: In constructor ‘Cell::Cell(int, int, int)’:
Cell-old.cpp:4:67: error: no matching function for call to ‘DS3904::DS3904()’
4 | Cell::Cell(int cellNumber, int digipotAddress, int resistorAddress) {
|
That's the first problem. You didn't specify a member initializer list, but _digipot
still has to be constructed, so the default is for the object's default constructor to be called, i.e. a constructor taking no arguments. But class DS3904
doesn't have such a constructor, so this is an error.
The second issue is that your statement _digipot(digipotAddress, 2);
in the body of the constructor isn't parsed as an attempt to call _digipot
's constructor (after all, that should be impossible, since by the time we get here it should already have been constructed). Instead, a statement of the form obj(arg, arg)
is applying the function call operator operator()
to obj
. If obj
were a function or a function pointer, this would simply call the function, but this operator can also be overloaded for other types; see Why override operator()? for some examples of where this is useful.
So the compiler looks for an overloaded DS3904::operator()
taking arguments compatible with what you've passed: an int
lvalue, which could be passed as a reference (int&
), and an int
rvalue, which would have to be passed by value. No such overload exists, so this results in your second error.
By the way, clang's error messages on this code are a bit clearer:
Cell-old.cpp:4:7: error: constructor for 'Cell' must explicitly initialize the member '_digipot' which does not have a default constructor
Cell::Cell(int cellNumber, int digipotAddress, int resistorAddress) {
^
./Cell.h:15:16: note: member is declared here
DS3904 _digipot;
^
./DS3904.h:27:7: note: 'DS3904' declared here
class DS3904
^
Cell-old.cpp:5:5: error: type 'DS3904' does not provide a call operator
_digipot(digipotAddress, 2);
^~~~~~~~
When faced with a confusing error message, it's often helpful to try a different compiler, and see if it can give you something more useful.