I've recently begun using C++ to try and program an Arduino library for a project I'm working on. In this library, I'm including another library published on GitHub, which I assume compiles on its own. As a part of the constructor for my class, I am creating and assigning an object of the published class. When I call the constructor, which takes two integers, with two integers, I get the following error:
Cell.cpp:7:31: error: no match for call to '(DS3904) (int&, int)'
_digipot(digipotAddress, 2);
^
EDIT: I was told by the comments before I edited this that a reference should work out just fine in this instance. Here is the library I am using. Following are the header file:
Cell.h:
#ifndef Cell_h
#define Cell_h
#include "Arduino.h"
#include "DS3904.h"
class Cell {
public:
Cell(int cellNumber, int digipotAddress, int resistorAddress);
void setCellVoltage(int voltage);
int getCellNumber();
private:
unsigned int _cellNo;
unsigned int _resistorAddress;
DS3904 _digipot;
};
#endif
And the actual C++ file, Cell.cpp (note that some unused functions are omitted from this one):
#include "Arduino.h"
#include "Cell.h"
Cell::Cell(int cellNumber, int digipotAddress, int resistorAddress) {
_digipot(digipotAddress, 2);
_cellNo = cellNumber;
_resistorAddress = resistorAddress;
}
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.
Related
I have the class
class A
{
public:
class Key
{
Key() {}
Key(Key const &) {}
};
A(Key key, int a = 5) {}
};
The constructor for Key is private, so no one should be able to construct an object A. However, with the following code:
int main() {
A a(A::Key()); // this compiles !!!
A a2(A::Key(), 5); // this doesn't
// somehow defaulting the argument causes the private constructor
// to be OK - no idea why
return 0;
}
By making use of the default argument for int a in my constructor, the compiler happily compiles my usage of A::Key() despite the fact that it is private. If I explicitly give a value for a, though, the compiler correctly recognizes that I am trying to use a private constructor and errors out. Why is this? Is there someway to force the compiler to error out for the first example as well?
See here for live example.
This is because of the most vexing parse.
A a(A::Key());
Does not create a A named a and construct it with a temporary A::Key. It creates a function a that returns an A and takes an unnamed pointer to function that returns a A::Key.
If you add a pair of parentheses to it you will get a compiler error
A a((A::Key()));
That you are trying to call a private constructor. Alternatively you can use uniformed initialization which also disambiguate it and will cause a compile error
A a(A::Key{});
I'm having trouble with something that seems very easy, so I must be overlooking something.
I need to construct a class that has a field that is also a class (non-POD). The class of the field has a default constructor and a "real" constructor. The thing is that I really can't construct the field in the initializer list, because in reality the constructor has a parameter that is a vector which needs a somewhat complex for loop to fill.
Here is a minimal example that reproduces the problem.
ConstructorsTest.h:
class SomeProperty {
public:
SomeProperty(int param1); //Ordinary constructor.
SomeProperty(); //Default constructor.
int param1;
};
class ConstructorsTest {
ConstructorsTest();
SomeProperty the_property;
};
ConstructorsTest.cpp:
#include "ConstructorsTest.h"
ConstructorsTest::ConstructorsTest() {
the_property(4);
}
SomeProperty::SomeProperty(int param1) : param1(param1) {}
SomeProperty::SomeProperty() : param1(0) {} //Default constructor, doesn't matter.
But this gives a compile error:
ConstructorsTest.cpp: In constructor 'ConstructorsTest::ConstructorsTest()':
ConstructorsTest.cpp:4:19: error: no match for call to '(SomeProperty) (int)'
the_property(4);
^
It gives no suggestions like it usually would of what functions could have been intended instead.
In the above example I would just initialize the_property in the initializer list, but in reality the 4 is actually a complex vector that needs to be generated first, so I really can't. Moving the_property(4) to the initializer list causes the compilation to succeed.
Other similar threads mention that the object must have a default constructor, or that it can't be const. Both requirements seem to have been met, here.
You can't initialize data member inside the constructor's body. (the_property(4); is just trying to invoke the_property as a functor.) You can only assign them like:
ConstructorsTest::ConstructorsTest() {
the_property = ...;
}
but in reality the 4 is actually a complex vector that needs to be generated first
You can add a member function which generate the necessary data, and use it to initialize the data member in member initializer list. e.g.
class ConstructorsTest {
...
static int generateData();
};
int ConstructorsTest::generateData() {
return ...;
}
ConstructorsTest::ConstructorsTest() : the_property(generateData()) {
}
You cannot initialize a variable twice.1 When your constructor has started, all member subobjects will have been constructed. If you do not provide a member initializer in the constructor, or a default member initializer in the class definition, then it will perform default initialization. Regardless of what form it takes, you can't construct it again.
Complex multi-statement initialization is best done via a lambda function:
ConstructorsTest::ConstructorsTest()
: the_property( []{ /* Do Complex Initialization */}() )
{
}
1: Well... you can, but not like that. And you really shouldn't for cases as simple as this.
Let's say I have the following definitions:
class ScriptInterpreter {
public:
class cell;
typedef ScriptInterpreter::cell (ScriptInterpreter::*proc_t) (const std::vector<cell> &);
class cell {
public:
proc_t proc;
};
ScriptInterpreter::cell proc_add(const std::vector<cell> & c);
};
And the following code going on:
ScriptInterpreter::eval(ScriptInterpreter::cell cell, environment * env)
{
// ...
ScriptInterpreter::cell c;
c.proc = &ScriptInterpreter::proc_add;
return (c.*proc_)(exps);
}
At the line where I try to call the function pointer I get the error
error: called object type 'proc_t' (aka 'ScriptInterpreter::cell (ScriptInterpreter::*)(const std::vector<cell> &)') is not
a function or function pointer
When I add the * in front of the func so the line looks like this:
ScriptInterpreter::cell c = (proc_cell.*proc_)(exps);
it produces this:
error: use of undeclared identifier 'proc_'
I already looked at Callback functions in c++ and other problems of that kind, but nothing really gave me a hint what's wrong or provided any information about my error. I definitely don't have any names twice or something of that kind.
Also after reading what is an undeclared identifier error and how do i fix it I'm pretty sure I got everything alright.
So what am I doing wrong?
Edit: updated the code with real code instead of placeholder code
In order to call a member function through a pointer of pointer-to-member type, you have to use either operator .* or operator ->*. And on the left-hand side you have to specify the object for which you want to invoke that member function.
In your case an attempt to do that could look as follows
A::B b_object;
b_object.func = &A::func_to_call;
A a_object;
A::B other_b_object = (a_object.*b_object.func)();
Note that since the pointer is declared as pointing to a member of A, the .* operator need an object of type A on the left-hand side.
However, in your specific case this is ill-formed since b_object.func is private and no accessible from main.
P.S. int main, not void main.
I have seen this question: Attempting to reference a deleted function (VS2013) but it didn't provide me an answer.
I have a member variable in class which its type is ofstream and a constructor which contains string parameter:
class dogs
{
public:
ofstream dogsFile;
dogs(string location)
{
}
};
The following error appears:
Error 2 error C2280: 'std::basic_ofstream>::basic_ofstream(const std::basic_ofstream> &)' : attempting to reference a deleted function c:\users\pc\documents\visual studio 2013\projects\database\database\database.cpp 26 1 Database
I have tried this code again but instead of using string I used char*:
class dogs
{
public:
ofstream dogsFile;
dogs(char* location)
{
}
};
And the error disappeared. Why? why does string makes the error?
Edit:
This is the whole code:
#include "stdafx.h"
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
class dogs
{
ofstream dogsFile;
public:
dogs(string location)
{
}
};
int main(int argc, _TCHAR* argv[])
{
dogs dog = dogs("dog.bin");
return 1;
}
The original answer by Dieter seems to be correct.
I.e. This will compile:
dogs *dog = new dogs("dog.bin");
Your line will not, see his answer about copy constructors.
the dogs("dog.bin") will create an object then "=" will make a copy of it and give it to dog. Can't copy object with ofstream in it.
You can also fix this by using
dogs dog("dog.bin");
instead.
I can't think of this as anything else than a bug in VC++.
The way the dogs class is defined, the compiler should generate an implicit move constructor for it, which will call the move constructor for std::ofstream, which is defined as of C++11.
The rules for when to define an implicit move constructor are specified in the standard in [12.8/9] and [12.8/11]. They're also listed here. I can't see any reason not to declare the implicit move constructor in this case.
Then, the line
dogs dog = dogs("dog.bin");
must invoke a move from the temporary dogs object on the right hand side to the left-hand-side dog (the move may be elided, but the constructor needs to be accessible nonetheless).
In short, everything should work fine.
And it does in Clang 3.5. It doesn't work in GCC, but only because it doesn't have move constructors defined for stream classes (it's not standard-compliant in that respect).
Funnily enough, it works in VC++, as the OP duly mentioned, if the dogs constructor is declared to take anything else but a std::string by value. Change the constructor to any of the following:
dogs(const string& location)
or
dogs(int a) //And change the call accordingly, of course.
or
dogs(A a) //And change the call accordingly (A is a user-defined class).
and everything will work fine in VC++, as it should.
The fact that it doesn't work only for std::string passed by value seems to indicate there's a bug in the compiler. Basically, in that case, and only in that case, the compiler decides not to define the implicit move constructor, which causes the copy initialization to fall back to calling the copy constructor, which causes the error.
If you explicitly define the move constructor, like this:
dogs(dogs&& arg) : dogsFile(std::move(arg.dogsFile)) { }
again, everything works fine, including with the constructor taking a std::string by value.
I can't see any valid reason for VC++ to behave this way.
I am working in c++.
my class animation.h is the following:
class Animation
{
public:
Animation(ofVec2f _startLoc, ofVec2f _endLoc, float _speed, float _accel);
virtual ~Animation();
};
then in sceneMusic.h I have another class that calls animation class.
#include "animation.h"
class sceneMusic
{
public:
sceneMusic();
virtual ~sceneMusic();
private:
Animation staveMotion;
};
and sceneMusic.cpp
sceneMusic::sceneMusic()
{
staveImg.loadImage("./sceneMusic/stave_white.png");
staveMotion = Animation(ofVec2f(29, -staveImg.height()), \
ofVec2f(29, 249), 1, 0.1);
}
The above gives the following (expected) error:
src/awards/sceneMusic.cpp|3|error: no matching function for call to ‘Animation::Animation()’|
src/awards/sceneMusic.cpp|5|note: candidates are:|
src/Animation.h|14|note: Animation::Animation(ofVec2f, ofVec2f, float, float)|
src/Animation.h|14|note: candidate expects 4 arguments, 0 provided|
I read alot of threads that suggest I should use initializer lists and do in sceneMusic.cpp
sceneMusic::sceneMusic()
:Animation(ofVec2f(29, -staveImg.height()), \
ofVec2f(29, 249), 1, 0.1)
{
staveImg.loadImage("./sceneMusic/stave_white.png");
}
or something similar.
The problem is that the height of staveImg will only become available once the constructor will be executed.
Also the class sceneMusic does not inherit class animation, therefore I am not sure how the above would work. If I attempt to run the above I get
src/awards/sceneMusic.cpp|4|error: type ‘Animation’ is not a direct base of ‘sceneMusic’|
src/awards/sceneMusic.cpp|4|error: ‘((sceneMusic*)this)->sceneMusic::staveImg.ofImage_<unsigned char>::height’ cannot be used as a function|
src/awards/sceneMusic.cpp|5|error: no matching function for call to ‘Animation::Animation()’|
src/awards/sceneMusic.cpp|5|note: candidates are:|
...
What am I doing wrong ?
thank you for your help
Well, the issue with your second attempt is you'd need to do this:
sceneMusic::sceneMusic()
:staveMotion(ofVec2f(29, -staveImg.height()), \
ofVec2f(29, 249), 1, 0.1)
You specify the member names in the initializer lists. You specify a class name only when you are attempting to call a specific super-class constructor. Animation is not a super-class of sceneMusic.
The following "no matching function for call to Animation::Animation()" occurred for the same reason it would have occurred if you didn't have anything in your initializer list at all: the staveMotion member was still trying to use Animations default constructor (just like the default constructor is used when you declare a variable Animation a;), but Animation does not have a default constructor.
Correcting the error in the initializer list takes care of both errors.
By the way, your second error regarding height(): make sure there's actually a member function named height(). You aren't showing the code but that error seems to indicate that you actually have a member variable named height, not a function.
However, the above still won't fix your issue with having to call loadImage first (thanks chris for reminding me about that in comments).
The easiest solution to that is to revert to your first attempt, and simply provide a default (no parameter) constructor for Animation. As soon as you declare a non-default constructor, the compiler no longer generates a default constructor for you, and you have to explicitly declare/define Animation::Animation() to provide it. That way, staveMotion can be constructed with some default values (and won't have to be constructed in your initializer list) and then assigned to a proper value later.
A second option, by the way, that wouldn't require creation of temporary default Animations first (or perhaps more importantly, wouldn't require you to implement a default constructor that possibly breaks class invariants), would be to have staveImg be a member field of sceneMusic, give it a constructor that takes an image filename and loads the image, and declare it before staveMotion in the member list. You wouldn't need an Animation default constructor for this, and you could initialize everything in the initializer list:
sceneMusic :: sceneMusic () :
staveImg("./sceneMusic/stave_white.png"),
staveMotion(ofVec2f(29, -staveImg.height()), ofVec2f(29, 249), 1, 0.1)
{
}
A variation on that option is to construct the image ahead of time and pass it as a parameter to the sceneMusic constructor. This wouldn't require a new constructor fo staveImg.
A third option, which CantChooseUsernames brought up in the comments, is to make staveMotion a pointer. You can initialize it to NULL and construct a new Animation(...) when necessary without requiring a default constructor. If you do this, don't forget to delete it when you are done. An automatic pointer such as std::unique_ptr<Animation> or one of the other smart pointers (boost has some too) can make that easier on you.
you need a default constructor class Animation since you provide parameter constructor ,the compiler would not generate one for you
Animation() {}