I have two objects, data
which is a large amount of data (duh) and node
which I plan to use in a tree, where each node contains data. I want to create a node
constructor where I pass it a data
object but I am getting the following error:
node.cpp: In constructor 'node::node(data&, std::vector<int>)': node.cpp:7:49: error: no matching function for call to 'data::data()' node::node(data &data0, vector<int> feature_list)
My constructors for data
are:
// "data.h"
13 // read the data from a file
14 data(string fname);
15
16 // data set based on other data set
17 data(data &data0, int iv_beg, int iv_end);
18
19 // data set based on other data set
20 data(data &data0, vector< int > vectors );
where the first one is such that I read the data from a file, the second two are methods for creating new data
objects from previous data
objects. The ability to pass data &data0
works fine in the data
cosntructors, but when I try to create a node
constructor:
// "node.h"
17 // create a node with the given data
18 // --- tell it what features it is allowed to branch on
19 node(data &data0, vector<int> feature_list);
I get the error. I know it is saying that I don't have a default constructor for data
, but why do I need one? I am passing an object which has already been defined. Does data::data()
, by default, allow for a copy or something that I'm not seeing? If so, why was I allowed to pass data &data0
to my data
constructors without it barking at me?
EDIT:
Simply placing data::data();
into my data.h
file and data::data() { }
into my data.cpp
file solves the problem, but I feel like there is something else going on - what am I missing about the way that objects get passed to constructors of other classes?
EDIT2: minimal code example.
"node.h":
1 #ifndef _NODE_H_
2 #define _NODE_H_
3
4 #include "data.h"
5 #include <vector>
6 #include <string>
7
8 class node {
9 public:
10 node(data &data0, vector<int> feature_list);
11 private:
12 data node_data; // data for this node
13 };
14 #endif
"node.cpp"
1 #include "node.h"
2 #include "data.h"
3 #include <vector>
4
5 node::node(data &data0, vector<int> feature_list) {
6 data0.print();
7 }
"data.h"
1 #ifndef _DATA_H_
2 #define _DATA_H_
3
4 #include <string>
5 #include <vector>
6
7 using namespace std;
8
9 /////// object to hold data
10 class data {
11
12 public:
13 // data set based on file
14 data(string fname);
15 // print the dat set
16 void print();
17 int nvectors();
18 int nfeatures();
19 vector< string > feature_names();
20 vector< double > feature_vector(int iv);
21
22 private:
23 void read_datfile();
24 string _fname;
25 vector< string > _features;
26 vector<vector< double > > _x;
27 int _Nf; // number of features
28 int _Nv; // number of feature vectors
29 };
30
31 #endif
"data.cpp"
1 #include "data.h"
2
3 #include <string>
4 #include <string.h>
5 #include <vector>
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <fstream>
9 #include <iostream>
10
11 using namespace std;
12
13 // data set which is derived fom a file
14 data::data(string fname) {
15 _fname = fname;
16 read_datfile();
17 }
18
19 // print the vectors in the data set
20 void data::print() {
21 int iv_beg = 0;
22 int iv_end = 2;
23
24 vector<double> tvect[_Nf];
25 if(iv_end < _Nv) {
26 for(int iv = iv_beg; iv<iv_end; iv++) {
27 printf("VECTOR %i\n", iv);
28 for(int ifeat = 0; ifeat<_Nf; ifeat++) {
29 printf("%25s ... %f\n", _features[ifeat].c_str(), _x[iv][ifeat]);
30 }
31 }
32 }
33 else {
34 printf("ERROR: there are not that many vectors in this data set\n");
35 }
36 }
37
38 // read the file
39 void data::read_datfile() {
...
87 }
I'm pretty sure the problem is that you don't put it in the initialiser-list. Showing your code for node
might help. If you don't give your data member some value in the initialiser-list its default constructor will be called then you use the affectation operator to change its value which is probably what you don't want to do. If your class node contains a pointer instead of a reference it will be fine even if you don't initialise it because a pointer doesn't have to be initialised but a value or a reference has to (hence the call to the default constructor).
What happens to node_data
when the node constructor starts running? What is it going to be set to? The compiler automatically attempts to call the default constructor.
This is another of an extremely long list of reasons why field initialization lists are ALWAYS best. If you set node_data
to data0
in the field initialization list, it will attempt to call your copy constructor instead of the default constructor (which it looks like you also don't have).
If you don't want to define a copy constructor, then just stick with the solution you have right now and create a default constructor that does nothing.
Also, you're double including a couple times (this won't cause problems because the STL classes are protected from that, it's just pointless code). If you include something in the .h
file, it is already automatically included in the .cpp
file when you do #include "foo.h"
EDIT (field initialization list and copy constructor):
class data {
public:
data(const data &that) { //Create the copy constructor
//Simply copy over all of the values
_fname = that._fname;
_features = that._features;
_x = that._x;
_Nf = that._Nf;
_Nv = that._Nv;
}
...
}
node::node(data &data0, vector<int> feature_list)
: node_data(data0) { } //Initialize node_data in the initialization list
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.