第二次上机实验代码调试总结
最近因为要忙着打比赛和各种各样的算法研究,所以导致正在上的C++这门科目有点落后,等这个星期过了才有空闲时间,再好好总结一下,现在就只有每个星期的上机课有一点时间来归类和总结,这次试验主要做的是类的组合,首先是我写的第一个不成熟的类的组合,主要是为了练一练基本的一个框架,然后顺便看一看构造函数和析构函数的调用顺序,下面放我写的第一个代码
#include<iostream>
using namespace std;
class Time
{
public:
Time(int a=22,int b=38,int c=56)
{
settime(a,b,c);//这里发现了构造函数的更简单的一个赋值的方法
cout<<"the (time)constructor has been used!"<<endl;
}
~Time(){
cout<<"调用Time析构函数"<<endl;//我在每一个地方都加了这样的标志性语句,
}; //我们可以更好的看见析构和构造函数的调用情况和顺序
void settime(int a,int b,int c)
{
hour=a;
minute=b;
second=c;
}
void showtime()
{
cout<<"时间是:"<<endl;
cout<<hour<<"-"<<minute<<"-"<<second<<endl;
}
private:
int hour;
int minute;
int second;
};
class Date
{
public:
Date(int a=2019,int b=3,int c=24,int e=22,int f=47,int g=58)
{
setdate(a,b,c,e,f,g);
cout<<"the (date)constructor has been used!"<<endl;
}
~Date(){
cout<<"调用Date析构函数"<<endl;
}
void setdate(int a,int b,int c,int e,int f,int g)
{
year=a;
month=b;
day=c;
t1.settime(e,f,g);
}
void showDateandTime()
{
cout<<year<<"-"<<month<<"-"<<day<<endl;
cout<<"然后是时间"<<endl;
t1.showtime();
}
private:
Time t1;
int year,month,day;
};
int main()
{
int y,m,d,h,minn,se;
while(cin>>y>>m>>d>>h>>minn>>se)
{
Time t1,t2(h,minn,se);
t1.showtime();
t2.showtime();
Date d1,d2(y,m,d,h,minn,se);
d1.showDateandTime();
d2.showDateandTime();
}
return 0;
}
下面是调试过后得到的结果
我们可以看见,构造函数的调用顺序就是按照我们创建对象的方式而来的,依次调用,而析构函数则与之对应正好成镜面对称,也就是 最后调用什么最先析构什么,然后从后往上依次进行。
然后我写的第二个代码主要是研究构造函数里面默认值的问题
主要是研究这个方面的问题
代码如下:
Test(int a,int b,int c);//标记一下,就是这个地方的探究,这个是在原public类里面的
Test::Test(int a,int b,int c)//对应地方的观察操作
{
settest(a,b,c);
cout<<"the second constructor has been used!"<<endl;
}
我想探究的四种情况如下:
第一种:
就是像最开始上面给的一样上面两个都不带参数;
第二种:
上面带有参数但是下面不带;
第三种:
上面带有参数而且下面也带有参数;
第四种:
上面没有参数但是下面带有参数;
首先是第一种:上面没有参数,下面也不带参数,就是没有默认的
#include<iostream>
using namespace std;
class Test
{
public:
Test();//这个地方的探究
~Test(){ cout<<"the x constructor has been used!"<<endl; }
Test(int a,int b,int c);//标记一下,就是这个地方的探究
void settest(int a,int b,int c);
void show();
private:
int ta,tb,tc;
};
Test::Test()
{
settest(0,0,0);
cout<<"the first constructor has been used!"<<endl;
}
Test::Test(int a,int b,int c)//对应地方的观察操作
{
settest(a,b,c);
cout<<"the second constructor has been used!"<<endl;
}
void Test::settest(int a,int b,int c)
{
ta=a,tb=b,tc=c;
}
void Test::show()
{
cout<<ta<<"--"<<tb<<"--"<<tc<<endl;
}
int main()
{
int a,b,c;
while(cin>>a>>b>>c)
{
Test t1;
t1.show();
Test t2(a,b,c);
t2.show();
}
return 0;
}
以下是对应的结果,正常:
下面是我测验的第二种情况,就是上面带有参数,而下面没有,我想看看默认参数有没有影响
第二种情况遇到了一个有趣的地方,就是我以前老师错的一个地方,正好这个程序测试出来了
代码如下:
//上面的
class Test
{
public:
Test();//这个地方的探究
~Test(){ cout<<"the x constructor has been used!"<<endl; }
Test(int a=1,int b=2,int c=3);//标记一下,就是这个地方的探究
void settest(int a,int b,int c);
void show();
private:
int ta,tb,tc;
};
//下面的
Test::Test(int a,int b,int c)//对应地方的观察操作
{
settest(a,b,c);
cout<<"the second constructor has been used!"<<endl;
}
//一部分的主函数
while(cin>>a>>b>>c)
{
Test t1;//跑的时候显示我这个地方有问题;!!!!!!
t1.show();
Test t2(a,b,c);
t2.show();
}
有问题的地方我在代码里面标了出来,为什么这个地方会有问题?
后来我知道问题在哪里了,就是Test t1,这个地方,当你创建的时候,后面什么都没有,上面有两个构造函数,
一个是 Test();
而另外一个是Test(int a=1,int b=2,int c=3);
对于下面一个构造函数来说,就算你什么都不传进去也没有问题,因为它含有默认的参数,所以传不传无所谓,所以他不知道到底是用第一个还是第二个,所以就会显示有跑的问题,把Test t1这个地方删除了,后面单独测试t2,是可以正常输出的。
而且还有一个错误,就是在定义里面Test t2();这样子写的话,这是一个声明,主函数里面声明是错的这样写!!!
——————————-分割线,下课了,我晚上再把其他的几种情况补上去
好的晚上我胡汉三又回来了,接着来写吧....
第三种情况,上面带有参数,下面也带有参数的...
代码如下:
//上面的
class Test
{
public:
Test();//这个地方的探究
~Test(){ cout<<"the x constructor has been used!"<<endl; }
Test(int a=1,int b=2,int c=3);//标记一下,就是这个地方的探究
void settest(int a,int b,int c);
void show();
private:
int ta,tb,tc;
};
//下面的
Test::Test(int a=4,int b=5,int c=6)//对应地方的观察操作
{
settest(a,b,c);
cout<<"the second constructor has been used!"<<endl;
}
直接显示编译错误,不能过
为了深入了解这个问题,我们把第四种情况也来试一下
//上面的改成这个样子
class Test
{
public:
Test();//这个地方的探究
~Test(){ cout<<"the x constructor has been used!"<<endl; }
Test(int a,int b,int c);//标记一下,就是这个地方的探究
void settest(int a,int b,int c);
void show();
private:
int ta,tb,tc;
};
//下面的改成这个样子
Test::Test(int a=4,int b=5,int c=6)//对应地方的观察操作
{
settest(a,b,c);
cout<<"the second constructor has been used!"<<endl;
}
结果这个样子过了,我们翻过去看看前一次的编译的错误提示:
这两个错误什么意思呢,就是直白的告诉你构造函数冠以默认和缺省的参数定义的这个地方有问题
我们其实可以很快得到相关结论:
既可以在类里面声明,也可以在类的定义里面缺省,或者都有,或者有一个,但就是不可以两个都有,不要重复定义默认函数,
最好在声明的地方定义,以免引起不必要的错误,