注册 登录
编程论坛 C++教室

各位高手,帮我看看这个代码运行结果呗~~~

sunflower44 发布于 2011-08-15 20:17, 564 次点击
#include<iostream>
using namespace std;
class ONE{
    int c;
public:
    ONE():c(0){cout<<1;}
    ONE(int n):c(n){cout<<2;}
};
class TWO{
    ONE one1;
    ONE one2;
public:
    TWO(int m):one2(m){cout<<3;}
};
int main(){
    TWO t(4);
    return 0;
}
13 回复
#2
sunflower442011-08-15 20:25
米人理我。。。。。。哎
#3
hoy0a1d2011-08-15 22:20
output: 123
#4
sunflower442011-08-15 23:05
回复 3楼 hoy0a1d
为什么会有那个1呢?
#5
xg56992011-08-16 00:15

因为TWO类中包含了2个ONE的对象,他们都是默认构造函数(无参),当TWO创建对象时会执行TWO类中的ONE one1;One one2;会输出 11
当然这是无参对象,而你创建是一个带参数的对象时则会调用带参的构造函数.
你的程序中TWO类带参的构造函数里修改了ONE类中one2的对象,所以one2这个对象根据你的修改直接运行带参构造函数而不是默认构造函数所以输出了2;
但one1这个对象是没有被修改,所以one1会调用他的默认构造函数输出1,由于TWO类中先创建one1所以先输出1,接着在创建one2(m),输出了2,接着么在输出了3

          如果你不能理解↑面的意思,那么你自己运行下下面的代码就会明白了
程序代码:
#include<iostream>
using namespace std;
class ONE
{
public:
    ONE(){cout<<"1"<<endl;}
};
class TWO
{
private:
    ONE a;
public:
    TWO(){};
};
void main()
{
    TWO a;
}



[ 本帖最后由 xg5699 于 2011-8-16 00:33 编辑 ]
#6
tiantiancc2011-08-17 01:01
TWO(int m):one2(m){cout<<3;}
one1调用默认构造函数,one2拷贝构造函数,然后cout<<3

建议好好看看复制控制章节,了解构造函数的调用规则。
#7
sunflower442011-08-17 08:56
回复 5楼 xg5699
#include<iostream>
using namespace std;
class ONE{
    int c;
public:
    ONE():c(0){cout<<1;}
    ONE(int n):c(n){cout<<2;}
};
class TWO{
    ONE one1;
    ONE one2;
public:
    TWO(int m):one2(m){cout<<3;}
};
int main(){
    TWO t(4);
    return 0;
}


我写一下这个程序运行的整个过程,帮我看下到底是哪一步有问题?

第一种过程:
由于TWO类中有子对象one1和one2,所以要先对t调用类ONE的构造函数。由于t被初始化为4,所以调用ONE带参数的构造函数,输出2.然后调用TWO的构造函数,把one2初始化为4,输出3.整个一来输出的结果是23.(这是我第一次的做题思路)

第二种过程:
由于TWO类中有子对象one1和one2,所以要先调用类ONE的构造函数,对one1和one2进行初始化。one1和one2均不带参,所以调用 ONE():c(0){cout<<1;},输出11,接下来调用TWO的构造函数,把one2初始化为4,输出3.这样结果就是113.
 
我上机试过了,结果确实是123.上面的程序过程错在哪里?能说一下正确的运行顺序吗?


#8
zhoufeng19882011-08-17 09:02
以下是引用tiantiancc在2011-8-17 01:01:36的发言:

TWO(int m):one2(m){cout<<3;}
one1调用默认构造函数,one2拷贝构造函数,然后cout<<3

建议好好看看复制控制章节,了解构造函数的调用规则。

哪儿调用了拷贝构造函数?
#9
zhoufeng19882011-08-17 09:08
1、Two t(4)————调用Two的构造函数。
2、Two的构造函数会按照成员变量的顺序依次进行初始化,如果程序员没有显示初始化的,就调用默认的构造函数。如果没有默认的构造函数,编译失败。
1)one1。调用默认的构造函数,输出1。
2)one2。调用带有一个int参数的构造函数,输出2。
3)再执行Two的构造函数函数体,输出3。

所以输出:123
#10
sunflower442011-08-17 09:42
回复 8楼 zhoufeng1988
我觉得也没用到拷贝构造函数啊,只不过是普通的构造函数而已。多了对子对象的初始化过程
#11
sunflower442011-08-17 09:47
回复 9楼 zhoufeng1988
2)one2。调用带有一个int参数的构造函数,输出2。
为什么调用带int参数的构造函数?
class TWO{
    ONE one1;
    ONE one2;

不是one2也不带参吗?



#12
xg56992011-08-17 11:44
回复 7楼 sunflower44
第二种过程:
由于TWO类中有子对象one1和one2,所以要先调用类ONE的构造函数,对one1和one2进行初始化。one1和one2均不带参,所以调用 ONE():c(0){cout<<1;},输出11,接下来调用TWO的构造函数,把one2初始化为4,输出3.这样结果就是113.
第二种过程:
由于TWO类中有子对象one1和one2,所以要先调用类ONE的构造函数,对one1和one2进行初始化(但你改变了one2的初始化,后面说)。one1和one2均不带参,先创建one1 所以调用 ONE():c(0){cout<<1;},输出1,
接下来创建one2 本来one2也是输出1,但因为调用的是TWO类带参的构造函数,TWO(int m):one2(m)初始化了one2(m),one2调用的就不是ONE的构造函数了
而是ONE类中带参的构造函数!
ONE(int n):c(n){cout<<2;}
所以输出了2而不是1


如果还是不明白你可以将代码TWO(int m):one2(m)将one2改成one1看下输出结果就会明白

[ 本帖最后由 xg5699 于 2011-8-17 11:57 编辑 ]
#13
xg56992011-08-17 12:10
如果你还是不明白呢,没关系,你按照我说的这么做,先上机运行下这个代码
程序代码:
#include<iostream>
using namespace std;
class ONE
{
public:
    ONE(){cout<<"1"<<endl;}
};
class TWO
{
private:
    ONE a;
public:
    TWO(){};
};
void main()
{
    TWO a;
}
不要直接运行,心理想下输出结果会是几,等有了结果在运行

运行后输出的结果和你心理想的一样那么在运行下面的代码
程序代码:
#include<iostream>
using namespace std;
class ONE
{
public:
    ONE(){cout<<"1"<<endl;}
    ONE(int a){cout<<"2"<<endl;}
};
class TWO
{
private:
    ONE a;
public:
    TWO(int b):a(b){};
};
void main()
{
    TWO a(2);
}
步骤还是同上,慢慢的你自己会会找到为什么的

#14
tiantiancc2011-08-17 14:59
不好意思,搞错。版主出马,果然一个顶俩啊,就是牛逼。
1