[英]Why does calling an overloaded constructor cause a call of the default constructor?
我的C ++程序总是调用比我想要的更多的构造函数。 它应该创建一个边缘,然后通过重载的边缘构造函数的字符串输入自动创建两个节点。
但是它首先调用节点对象的默认构造函数,然后调用重载的自定义构造函数。 析构函数不会立即删除默认节点。 那会导致我的程序出错。
问题在于程序应计算对象数量并分配与对象数量相关的适当ID。
编译器输出
Default-Constructor
Default-Constructor
Overload-Constructor
ID: 1 numInstances: 2
Destructor
Overload-Constructor
ID: 2 numInstances: 1
Destructor
Edge: -> Node_0002
Destructor
Destructor
Program ended with exit code: 0
这是一个片段,供您查看最有可能导致该错误的代码:
main.cpp
int main() {
Edge e1 = Edge("1", "2");
std::cout << "Edge: " << e1.toString() << endl;
return 0;
}
node.hpp
double Node::numInstances = 0;
Node::Node()
{
numInstances++;
cout << "Default-Constructor" << endl;
double idNumber = numInstances;
m_id = setUpIdString(idNumber);
}
Node::Node(string id)
{
double idNumber = getNumberFromString(id);
cout << "Overload-Constructor" << endl;
cout << "ID: " << idNumber << " numInstances: " << numInstances << endl;
if (idNumber > numInstances) {
numInstances++;
m_id = setUpIdString(idNumber);
}
}
Node::~Node()
{
numInstances--;
cout << "Destructor" << endl;
}
edge.cpp
Edge::Edge(string src, string dst)
{
m_srcNode = Node(src);
m_dstNode = Node(dst);
}
编辑:
node.hpp
class Node
{
public:
Node();
Node(string id);
~Node();
string getId();
private:
string m_id;
static double numInstances;
};
edge.hpp
class Edge
{
public:
Edge(Node& rSrc, Node& rDst);
Edge(string src, string dst);
string toString();
Node& getSrcNode();
Node& getDstNode();
private:
Node m_srcNode;
Node m_dstNode;
};
构造函数与C ++中的其他函数不同。 构造函数的工作是初始化一个对象。 为了确保以合理的方式初始化对象,需要初始化所有成员对象(和基础对象)。 *这发生在构造函数主体的大括号之前 ,因此当您在构造函数主体中时,一切都处于明智的状态。
为了确保按照您希望的方式进行操作,可以使用初始化程序列表 (请注意,在初始化各种容器时,该术语还指其他内容;如果您之前听说过与此相关的术语,那不是我所想的)我在这里讨论)。 在函数签名之后,放一个冒号,后跟类中的每个成员(按照它们在类中声明的顺序)以及如何初始化它。 例如,如果您具有以下struct
struct A {
int i;
char c;
std::string s;
A();
};
您可以声明将构造函数定义为
A::A() : i{17}, c{'q'}, s{"Hello, mrb! Welcome to Stack Overflow"}
{
// Nothing to do in the body of the constructor
}
这样, A
对象的成员在函数开始之前被初始化为17
, 'q'
和问候语,而没有其他任何方式被初始化。
由于不执行此操作,因此编译器将对节点使用默认构造函数。 然后,您可以在构造函数主体内创建其他节点,并将它们分配给类中的节点。
m_srcNode = Node(src);
m_dstNode = Node(dst);
在这里,首先使用默认构造函数构造这两个对象,然后使用Node(src)
和Node(dst)
调用重载的构造函数。 之后,将调用隐式定义的副本分配器 ,以将临时对象分配给m_srcNode
和m_dstNode
。 最后,临时对象被销毁。
如果要避免额外的构造函数调用,可以编写成员初始化器列表 :
Edge::Edge(string src, string dst) : m_srcNode(src), m_dstNode(dst) {}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.