2

I'm writing some C++ classes where one class has an instance of another class as an attribute. When writing the class constructors I keep getting the error "no default constructor exists for class Foo". Here's a small example reproducing the error:

class Foo {
    int size;
    char name;
    Foo(int s,char n) {
        size = s;
        name = n;
    }
};

class Bar {
    int size;
    char name;
    Foo foo;
    Bar(int s, char n,Foo f){
        size = s;
        name = n;
        foo = f;
    }
};

The error disappears if I remove the class constructor for Foo so that the default constructor is used. Since I'm passing an existing instance of the class Foo into the constructor for Bar, I don't understand why the error talks about the constructor for Foo. Why does the error occur? And how can the code be fixed?

ducksforever
  • 177
  • 4

1 Answers1

5

You should be initializing via initialization lists, not via assignment.

// You probably want these to be a struct, not class.
// This way all members are public by default.
struct Foo {
    int size;
    char name;

    Foo(int s,char n) : size{s}, name{n} {}
};

struct Bar {
    int size;
    char name;
    Foo foo;

    Bar(int s, char n, const Foo &f) : size{s}, name{n}, foo{f} {}
};

When you don't initialize member variables in the initialization list, that's the same as default-constructing it and then re-assigning the values. So you are doing twice the work for no reason. (Also see Constructors and member initializer lists)

Because you have defined a constructor for your structs, the default constructor is implicitly deleted which caused your compilation error.

On a side note, you might not even need these constructors and can use aggregate initialization instead, like this:

struct Foo {
    int size;
    char name;
};

void example() {
    Foo foo = {1, 'a'}; // the = is optional
}
Jan Schultke
  • 17,446
  • 6
  • 47
  • 96
  • Thanks for the help :) Why do we use the constant keyword in front of Foo in the initialisation list for Bar? – ducksforever Aug 18 '20 at 18:55
  • 1
    @ducksforever it means that we take `Foo` as a `const` reference. This avoids an unnecessary copy. It's generally good practice to not take everything as a value, in this case it won't make much of a difference though. – Jan Schultke Aug 18 '20 at 19:37