No appropriate default constructor for struct?

Hi Guys,

Having a very weird issue. I know I've done this a million times and never gotten an error, not sure why I'm getting one now.

Basically, being told I need a default constructor to make a basic struct. Here's the code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
class TrainList{
    public:
        struct tNode{
            Train data;
            tNode * next;
        };
        TrainList();
        ~TrainList();         
        bool isEmpty();
        void add(Train P);
        tNode * find(int pos);
        void remove(Train P);
        int getSize();          
        Train remove(int pos);             //Removes & deletes a node
        Train retrieve(int pos);           //Retrieves the data of node
        void displayList();
    private:
        tNode * head;
        int size;
};

TrainList::TrainList() {
	size = 0;
	head = new tNode;
}


And here's the error:


trainlist.hpp(24): error C2512: 'TrainList::tNode' : no appropriate default constructor available



The bizarre thing is that I have another class in the same project that is literallyan exact copy of this one except it's for a different type of object (passenger) and that one compiles without a problem.

As a solution, I tried declaring the struct like this:

1
2
3
4
5
struct tNode{
   Train data;
   tNode * next;
   tNode(){}
};


But then I get an error that I needed a constructor Train() for that to work.

Anyone know why I'm having this problem?

Much thanks!
Last edited on
Train might not have a default constructor, which means that a tNode object cannot be constructed without explicitly calling a separate ctor for it.

Can you post your Train class? Or really just the constructor(s).
It won't let me make a default constructor for Train, because the non-default constructors take references at parameters. Like this:

1
2
3
4
5
6
7
Train::Train(CTrainLine &tLine, Platform start, PassengerManager &pMan): trainline(tLine), passMan(pMan){
    location = start.getStation();
    currPlat = start;    
    nextPlat = *(tLine.getNext(start));
    tripTime = 0;
    status = "traveling";
}


When I try to write an empty default constructor JUST for the node:

1
2
3
Train::Train(){
    
}


I get this error:


uninitialized reference member `Train::passMan'

uninitialized reference member `Train::trainline'


So I tried doing this:


1
2
3
Train::Train(): trainline(new CTrainLine), passMan(new PassengerManager){
    
}


But then I get this error:


invalid initialization of non-const reference of type 'PassengerManager&' from a temporary of type 'PassengerManager*'

invalid initialization of non-const reference of type 'CTrainLine&' from a temporary of type 'CTrainLine*'


So not sure what to do here.
Okay that's your problem.

References need to be constructed explicitly (they do not have a default constructor). So since your Train class has references as members, you would need to initialize them in your default constructor.

However that's difficult/impossible to do correctly because I assume the stuff is supposed to be referencing things outside the class.


This is one of the reasons why I generally don't have reference as class members. It's rarely justifiable.

I recommend changing trainline and passMan to be pointers instead of references. Then in your default constructor initialize them to null (do not allocate with new -- that makes little/no sense). This also means you'll have to have some other kind of initialize function where you can set these members.
Or, write a copy constructor for `Train' that copies the references.
Use it to construct your nodes.

There's still the problem of your dummy header, use a dummy node for that.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class train_list{
private:
   struct dummy_node{
      dummy_node *next;
      dummy_node(){
         next = this; //or NULL, but initialize it
      }
   };
   struct tNode: public dummy_node{
      Train data;
      tNode(const Train &data): data(data){}
   };

   dummy_node header; //I don't understand why you used a pointer here
};


whenever you need to access the `data' field, just cast the node (it's an error to want to cast the header cell).


Don't force a default constructor if it makes no sense.
Topic archived. No new replies allowed.