C++复制构造函数和构造函数调用小困惑

最近看清华大学郑莉老师的C++课程,过C++的基础知识。遇到了一点小问题。
B站清华大学C++课程
在进行类组合例子的调试中,有些不解的地方。先上代码。

#include "pch.h"
#include <iostream>
using namespace std;

class Point {
public:						//外部接口
	Point(int xx = 0, int yy = 0) {		//构造函数
		x = xx;
		y = yy;
	}
	Point(Point &p);		//复制构造函数
	int getX() {
		return x;
	}
	int getY() {
		return y;
	}
private:				//私有数据
	int x, y;
};

//成员函数的实现
Point::Point(Point &p) {
	x = p.x;
	y = p.y;
	cout << "Calling the copy constructor" << endl;
}

class Line{
public:
	Line(Point xp1, Point xp2);
	Line(Line &l);
	double getLen() { return len; }
private:
	Point p1, p2;
	double len;
};
Line::Line(Point xp1, Point xp2):p1(xp1),p2(xp2)
{
	//p1 = xp1;
	//p2 = xp2;
	cout << "Calling constructor of Line" << endl;
	double x = static_cast<double>(p1.getX() - p2.getX());
	double y = static_cast<double>(p1.getY() - p2.getY());
	len = sqrt(x*x + y * y);
}

Line::Line(Line &l):p1(l.p1), p2(l.p2) 
{
	//p1 = l.p1;
	//p2 = l.p2;
	cout << "Calling the copy constructor of Line" << endl;
	len = l.len;
}

int main()
{
	Point myp1(1, 1), myp2(4, 5);
	Line line(myp1, myp2);
	Line line2(line);
	cout << "The lenth of the line is: " << line.getLen() << endl;
	cout << "The lenth of the line2 is: " << line2.getLen() << endl;
	return 0;
}

在这里插入图片描述
Point的复制构造函数共调用了6次。
而简单替换两个函数:

Line::Line(Point xp1, Point xp2)//:p1(xp1),p2(xp2)
{
	p1 = xp1;
	p2 = xp2;
	cout << "Calling constructor of Line" << endl;
	double x = static_cast<double>(p1.getX() - p2.getX());
	double y = static_cast<double>(p1.getY() - p2.getY());
	len = sqrt(x*x + y * y);
}

Line::Line(Line &l)//:p1(l.p1), p2(l.p2) 
{
	p1 = l.p1;
	p2 = l.p2;
	cout << "Calling the copy constructor of Line" << endl;
	len = l.len;
}

结果如下:
在这里插入图片描述
Point的复制构造函数共调用了2次。
非常不解。
p1 = xp1;与p1(xp1)不是一样的嘛?
先记录下来。


问题初步解决:

Line::Line(Point xp1, Point xp2)//:p1(xp1),p2(xp2)
{
	Point p1 = xp1;
	Point p2 = xp2;
	cout << "Calling constructor of Line" << endl;
	double x = static_cast<double>(p1.getX() - p2.getX());
	double y = static_cast<double>(p1.getY() - p2.getY());
	len = sqrt(x*x + y * y);
}

Line::Line(Line &l)//:p1(l.p1), p2(l.p2) 
{
	Point p1 = l.p1;
	Point p2 = l.p2;
	cout << "Calling the copy constructor of Line" << endl;
	len = l.len;
}

可实现六次调用复制构造函数
但,新问题出现:调试的时候发现Line::Line(Point xp1, Point xp2)首先调用了Point的构造函数,并初始了p1,p2为(0,0),这又是为什么呀?

<think>好的,我现在需要解决用户的问题:在C#中,如果一个结构体(struct)只有带参数的构造函数,如何在(class)的构造函数中实例化这个结构体。我得仔细分析这个问题,确保给出的答案正确且易于理解。 首先,我要确认用户使用的编程语言。虽然问题中没有明确提到,但结构体的概念在多种语言中存在,比如C#C++。不过,根据常见的用法,尤其是在C#中,结构体可以有构造函数,而用户提到的“带参数的构造”可能指的是C#的情况,因为例如在C#中,结构体可以有带参数的构造函数,而默认无参构造函数总是存在的,但用户可能遇到了需要显式调用带参数构造函数的情况。不过,实际上在C#中,结构体不能包含显式的无参构造函数,所有结构体都有一个隐式的无参构造函数,即使定义了带参数的构造函数。这可能让用户感到困惑,特别是当他们尝试在中实例化结构体时。 接下来,我需要回忆C#中结构体的实例化方式。当结构体有带参数的构造函数时,必须显式调用构造函数,不能使用隐式的无参构造函数(尽管隐式的存在)。因此,在构造函数中实例化结构体时,必须使用new关键字并传入所需参数。例如: public struct MyStruct { public int Value; public MyStruct(int value) { Value = value; } } 然后在中: public class MyClass { private MyStruct myStruct; public MyClass(int value) { myStruct = new MyStruct(value); } } 这样就能正确实例化结构体了。需要注意的是,即使结构体有带参数的构造函数,仍然可以通过隐式无参构造函数来初始化,但所有字段必须被显式赋值。例如,如果结构体没有定义带参数的构造函数,可以直接用new MyStruct(),但如果有带参数的构造函数,并且用户希望使用它,就必须传递参数。 用户可能遇到的另一个问题是,如果结构体的字段没有在带参数的构造函数中完全初始化,或者结构体的定义有误。例如,在C#中,结构体的构造函数必须初始化所有字段,否则会编译错误。因此,在定义结构体的构造函数时,必须确保所有字段都被赋值。 此外,用户可能想知道是否可以在不调用构造函数的情况下实例化结构体。在C#中,结构体是值型,可以不用new来实例化,但这样所有字段需要在使用前被显式初始化。例如: MyStruct myStruct; myStruct.Value = 10; // 必须初始化所有字段 但在这种情况下,如果结构体有带参数的构造函数,用户可能更倾向于调用构造函数来确保正确初始化。 总结下来,解决步骤应该是: 1. 确保结构体的带参构造函数正确初始化了所有字段。 2. 在构造函数中使用new关键字带参数的构造函数来实例化结构体。 3. 处理可能的编译错误,如未正确初始化字段或参数不匹配。 需要提醒用户注意结构体的不可变性,可能需要使用readonly struct来确保不可变,但这可能超出当前问题的范围。另外,结构体作为值型在赋值时的复制行为也需要留意,但用户的问题主要集中在实例化上。 最后,编写示例代码时,要确保语法正确,特别是C#中的结构体的定义,构造函数调用方式。同时,指出可能的常见错误,比如忘记初始化所有字段,或者试图使用隐式无参构造函数导致的问题。</think>在C#中,当结构体(`struct`)**只有带参数的构造函数**时,在中实例化它需要显式调用构造函数。以下是分步说明示例: --- ### 1. **定义带参数的结构体** 首先确保结构体的构造函数正确初始化了所有字段: ```csharp public struct MyStruct { public int X; public int Y; // 带参数的构造函数(必须初始化所有字段)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值