-2

I've a class called Socket, with two constructors:

Socket(int port){...} 
Socket(string address, int port){...}

I'd like to use one instance of that Socket class as a private member of another class, the Connection class, like this:

class Connection{
   private:
     Socket socket;
     //more stuff
};

In the constructor of the Connection class I just want to pass as parameter one instance of Socket and assign it to the private member, like this:

Connection:Connection(Socket socket){
   this->socket = socket;
   //...
}

But the compiler asks me to call the Socket constructor inside the Connection constructor (or at least I think that); I'm getting this error:

error: no matching function for call to ‘Socket::Socket()’ Connection::Connection(Socket socket)

Which is the right way to do that (declaring the Socket outside and passing it as parameter in the Connection constructor)?

Ron
  • 14,674
  • 4
  • 34
  • 47
pitazzo
  • 1,125
  • 1
  • 13
  • 28
  • Possible duplicate of [calling constructor of a class member in constructor](https://stackoverflow.com/questions/7761676/calling-constructor-of-a-class-member-in-constructor) – Tadeusz Kopec for Ukraine Dec 30 '17 at 13:26

4 Answers4

2

Use member initializer list instead, e.g.

Connection:Connection(Socket socket) : socket(socket) {}

For members that cannot be default-initialized, such as members of reference and const-qualified types, member initializers must be specified.

For your approach, the data member socket has to be default initialized at first, then assigned in the constructor's body. But Socket doesn't have default constructor and can't be default initialized.

BTW: The default constructor won't be implicitly generated for Socket because it has user-provided constructors.

songyuanyao
  • 169,198
  • 16
  • 310
  • 405
2

You're actually assigning a new Socket to the default constructed socket member. And since there's no default constructor for Socket class, compiler gives you that error.

// Here, 'socket' is assigned to the default constructed 'this->socket'.
this->socket = socket;

To initialize/construct the this->socket, you should write it in the member initializer list:

Connection:Connection(Socket socket) : socket(socket) {
}

This way, this->socket is copy constructed from the given socket.

frogatto
  • 28,539
  • 11
  • 83
  • 129
2

What happens in the Connection constructor is that the socket member is first default constructed, as part of the object initialization. And you don't have a Socket default constructor (a constructor which takes no arguments).

After that, the body of the constructor is executed, and the copy assignment is made (to an already existing object).

You should use a constructor initializer list to construct/initialize the members:

Connection:Connection(Socket socket)
    : socket(socket)
{}

On a very related note: The socket object inside the Connection object is a copy of the actual Socket instance! What happens in the above initializer list is that the socket object is copy-constructed.

You should probably use references if you want to reference the original Socket:

class Connection
{
    ...
    Socket& socket;
};
Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
  • Thanks so much for your clarifying answer. Do you know it is there any problem with using a copy of the Socket instead of the original? My Socket class works with UNIX socket system calls. – pitazzo Dec 30 '17 at 13:15
  • @pitazzo Not knowing what the `Socket` class does internally, I really can't say. It really depends on what you're doing, on the use-case. – Some programmer dude Dec 30 '17 at 13:22
1

Like said above, the data member socket is already default-constructed at the point the copy-assignment is called:

{
  // this->socket is already default-constructed here
  // but no default constructor Socket() available -> ERROR
  this->socket = socket;
}

That for the Socket constructor should be explicitely called, and that has to be within Connection constructor initliazer list (outside the constructor function body):

Connection::Connection(Socket sock) : socket(sock) {}

If you want a socket copy within your Connection class, you probably want to use

Connection::Connection(const Socket& sock) 

instead of Connection::Connection(Socket sock)

StPiere
  • 4,113
  • 15
  • 24