我有一个名为Socket
的类,有两个构造函数:
Socket(int port){...}
Socket(string address, int port){...}
我想将该Socket类的一个实例用作另一个类的私有成员Connection类,如下所示:
class Connection{
private:
Socket socket;
//more stuff
};
在Connection
类的构造函数中,我只想作为参数传递Socket
的一个实例,并将其分配给私有成员,如下所示:
Connection:Connection(Socket socket){
this->socket = socket;
//...
}
但是编译器要求我在Connection构造函数中调用Socket
构造函数(或者至少我认为);我收到了这个错误:
错误:没有匹配函数来调用'Socket :: Socket()' Connection :: Connection(套接字套接字)
这是正确的方法(在Socket
构造函数中声明Connection
外部并将其作为参数传递)?
答案 0 :(得分:2)
请改用member initializer list,例如
Connection:Connection(Socket socket) : socket(socket) {}
对于无法进行默认初始化的成员,例如引用成员和const限定类型,必须指定成员初始值设定项。
对于您的方法,数据成员socket
必须首先默认初始化,然后在构造函数体中分配。但是Socket
没有默认构造函数,不能默认初始化。
BTW:Socket
的默认构造函数不是implicitly generated,因为它有用户提供的构造函数。
答案 1 :(得分:2)
您实际上是在默认构建的 Socket
成员中分配了新的socket
。由于Socket
类没有默认构造函数,编译器会给出错误。
// Here, 'socket' is assigned to the default constructed 'this->socket'.
this->socket = socket;
要初始化/构造this->socket
,您应该将其写在成员初始化列表中:
Connection:Connection(Socket socket) : socket(socket) {
}
这样,this->socket
是来自给定socket
的复制构建。
答案 2 :(得分:2)
Connection
构造函数中发生的事情是socket
成员是第一个默认构造的,作为对象初始化的一部分。而且你没有Socket
默认构造函数(一个不带参数的构造函数)。
在之后,执行构造函数的主体,并进行 copy 赋值(对于已经存在的对象)。
您应该使用构造函数初始化列表来构建/初始化成员:
Connection:Connection(Socket socket)
: socket(socket)
{}
在一个非常相关的说明中:socket
对象中的Connection
对象是实际Socket
实例的副本!上面的初始化列表中发生的情况是socket
对象是复制构造的。
如果要引用原始Socket
,则应该使用引用:
class Connection
{
...
Socket& socket;
};
答案 3 :(得分:1)
如上所述,数据成员套接字在调用复制赋值时已经默认构造:
{
// this->socket is already default-constructed here
// but no default constructor Socket() available -> ERROR
this->socket = socket;
}
应该明确地调用Socket构造函数,并且必须在Connection构造函数initliazer列表中(在构造函数体外):
Connection::Connection(Socket sock) : socket(sock) {}
如果您想在Connection类中使用套接字副本,则可能需要使用
Connection::Connection(const Socket& sock)
而不是Connection::Connection(Socket sock)