1

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 }
3
  • I'm a bit confused by your question. The whole point is that data is not being constructed inside node, the data object is just being passed. It has already been constructed and has all the information it needs. Commented Jul 8, 2014 at 20:47
  • 2
    The code you're showing us is fine. The code you're not showing us has an error. See How to create a Minimal, Complete, and Verifiable example Commented Jul 8, 2014 at 20:49
  • Thanks, should I close this and open up a new question showing all code pertinant code or just update this? Commented Jul 8, 2014 at 20:55

2 Answers 2

2

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
Sign up to request clarification or add additional context in comments.

8 Comments

Thanks, I created a default constructor that does nothing and it fixed the problem. If it calls the default constructor, then why is the correct data node member resulting upon entering the node constructor? After creating the default (empty) constructor for data, it correctly printed out the contents of the passed data object, but if the default constructor was called, the information in data would be empty, right?
@Laurbert515 Be careful. I don't know what you're data member is called, but please give us its name and rephrase your comment with it so this doesn't become more confusing. I don't understand then why is the correct data node member resulting upon entering the node constructor?
Thanks, I am trying to pass a data object called data0 to my node. If I place a blank data::data() constructor, which really doesnt do anything at all, why is it that upon passing data0 to my node constructor, I am able to print the contents of data0 inside the node constructor?
@Laurbert515 The default constructor isn't getting called on data0. data0 is already a full fledged instance of the data class. By "data node member variable," I meant node_data. THAT is the data instance that is calling the default constructor.
@Laurbert515 I've edited my answer in an attempt to make things more clear^
|
2

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).

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.