对象作为类的私有成员

时间:2023-01-15 15:22:16

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

我有一个名为Socket的类,有两个构造函数:

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:

我想使用该Socket类的一个实例作为另一个类的私有成员,Connection类,如下所示:

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类的构造函数中,我只想作为参数传递一个Socket实例并将其分配给私有成员,如下所示:

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:

但是编译器要求我在Connection构造函数中调用Socket构造函数(或者至少我认为);我收到这个错误:

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

错误:没有匹配函数来调用'Socket :: Socket()'Connection :: Connection(套接字套接字)

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

哪种方法是正确的(将Socket声明为外部并将其作为Connection构造函数中的参数传递)?

4 个解决方案

#1


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

在Connection构造函数中发生的事情是,作为对象初始化的一部分,套接字成员首先是默认构造的。而且你没有Socket默认构造函数(一个不带参数的构造函数)。

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.

在一个非常相关的说明:Connection对象内的套接字对象是实际Socket实例的副本!上面的初始化列表中发生的是socket对象是复制构造的。

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

如果要引用原始Socket,则应该使用引用:

class Connection
{
    ...
    Socket& socket;
};

#2


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.

您实际上是将新Socket分配给默认构造的套接字成员。由于Socket类没有默认构造函数,编译器会给出错误。

// 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:

要初始化/构造this-> socket,您应该在成员初始化列表中编写它:

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

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

这样,this-> socket是从给定套接字构造的。

#3


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.

对于无法进行默认初始化的成员(例如引用成员和const限定类型),必须指定成员初始值设定项。

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.

对于您的方法,数据成员套接字必须首先默认初始化,然后在构造函数体中分配。但是Socket没有默认构造函数,不能默认初始化。

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

BTW:不会为Socket隐式生成默认构造函数,因为它具有用户提供的构造函数。

#4


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

应该明确地调用Socket构造函数,并且必须在Connection构造函数initliazer列表中(在构造函数体外):

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

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

如果您想在Connection类中使用套接字副本,则可能需要使用

Connection::Connection(const Socket& sock) 

instead of Connection::Connection(Socket sock)

而不是Connection :: Connection(插座袜子)

#1


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

在Connection构造函数中发生的事情是,作为对象初始化的一部分,套接字成员首先是默认构造的。而且你没有Socket默认构造函数(一个不带参数的构造函数)。

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.

在一个非常相关的说明:Connection对象内的套接字对象是实际Socket实例的副本!上面的初始化列表中发生的是socket对象是复制构造的。

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

如果要引用原始Socket,则应该使用引用:

class Connection
{
    ...
    Socket& socket;
};

#2


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.

您实际上是将新Socket分配给默认构造的套接字成员。由于Socket类没有默认构造函数,编译器会给出错误。

// 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:

要初始化/构造this-> socket,您应该在成员初始化列表中编写它:

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

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

这样,this-> socket是从给定套接字构造的。

#3


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.

对于无法进行默认初始化的成员(例如引用成员和const限定类型),必须指定成员初始值设定项。

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.

对于您的方法,数据成员套接字必须首先默认初始化,然后在构造函数体中分配。但是Socket没有默认构造函数,不能默认初始化。

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

BTW:不会为Socket隐式生成默认构造函数,因为它具有用户提供的构造函数。

#4


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

应该明确地调用Socket构造函数,并且必须在Connection构造函数initliazer列表中(在构造函数体外):

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

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

如果您想在Connection类中使用套接字副本,则可能需要使用

Connection::Connection(const Socket& sock) 

instead of Connection::Connection(Socket sock)

而不是Connection :: Connection(插座袜子)