c++问题,不会不要瞎答谢谢
发布网友
发布时间:2024-09-07 07:44
我来回答
共5个回答
热心网友
时间:2024-10-28 06:49
我不知道你用的什么编译器,但是在GCC标准ISO的编译器下面,这段程序是一定出错的。
出错的原因是print(l)会报ambiguous错误。即匹配模糊。
至于你问的输出顺序的问题,前面几位答的都很清楚了。
下面我就谈谈标准C++里关于函数重载参数匹配的过程。
重载确定有三个步骤:
1.候选函数。
重载确定的第一步是确定要考虑的都会有哪些函数。只要是函数名与被调用名同名的函数,都是候选函数。
2.选择可行函数。
可行函数有两个要求。
第一个要求是可行函数的函数参数个数和调用的函数参数个数必须相同,或者可行函数的参数能够多一些,但是多出来的函数参数都要有相关的缺省值.
(如 print(double , double =1.2 );如果有调用double a=1.0;print(a),则会将此函数选出作为可行函数)
第二个要求是根据参数类型的转换规则可以将被调用的函数实参转换成候选函数的实参。这里本着充分利用参数类型转换的原则,换句话说,尽可能的使用上参数类型转换。当然转换要以候选函数为转换的目标。
假如依照参数转换规则没有找到可行函数,则该调用就是错误的,则说没有函数和调用匹配,属于无匹配情况(no match function)。
3.选择最佳可行函数。
你的程序的问题就出在这一步。
选择最佳可行函数是在参类型转换基础上,选择出最佳的类型转换。
为了确定最佳匹配,标准C++将实参类型到相应形参类型的转换划分为四个等级:
1.精确匹配
2.类型提升
3.标准转换
4.通过类类型的转换
这里面比较容易出错的就是类型提升和标准转换之间及其微小的差异。类型提升的优先级是高于标准转换的,而类型提升之间又有不同的优先级。
我所接触到的类型提升,大部分都是整形提升。莫过于short,unsigned short,char,unsigned char到int之间的提升。只要该类型的所有可能都能被int型包容,则都会提升为int型。否则就是unsigned int型.long和unsigned int转换也是一样的,只要机器上的long足够表示unsigned int,就会将unsigned int转换成long.这取决于机器上这些类型的位数。这里需要注意的是,较小的类型提升为int型。比如char型可以转换到short型,但是在实际匹配中,如果有short和int两种形参,还是会选择int型。
观察一下你的程序,long面对int和double,在标准C++里面整形到double,float不属于类型提升,你可以回忆一下计算机内部double型和float型的数据表示就能明白为什么了。不管是int,char,short等等,到float和double的转换,都不属于类型提升,都属于标准转换,比如我们常说的int a=3,a+3.75,我们平常总是说将a提升到了double型。其实计算机在计算时,为了防止数据的丢失,将低层数据进行了标准转换。但是这在我们重载里面,不属于类型提升的范畴。而long到int,就更不属于数据提升了。
举个例子。
float print(float d) {cout<<" b "<<endl;return 2*d;}
double print(double d) {cout<<" b "<<endl;return 2*d;}
int a=3;调用print(a)的时候,顺着匹配步骤,和你的函数一样,可以一直到选择最佳可行执行函数的第三步->标准转换。
而在标准转换里,要注意一句话:任何标准转换都不比其他的标准转换具有更高的优先级。(我想可能是因为转换所作的工作都差不太多。所以编译器没有强调怎么转换会更优秀。)
到这里,你的问题就结束了。当long面对int和double时,因为同属于标准转换,所以没有优先级之分。当编译器面对这具有二义性的调用时,就傻眼了。(可以用强制转换print(static_cast<int>(l)),来强制让它使用某个函数。太过分的纠缠于此没有太多好处。)
而你所用的编译器,我想应该是VC或者其他的编译器,不是太遵循标准C++的规定。其实学习C++,最好还是不要局限于编译器。标准C++是最好的选择:(
附上你的代码在gcc 4.1.3下的编译错误error: call of overloaded ‘print(long int&)’ is ambiguous
参考自:C++ primer 第四版,希望能给楼主解惑。欢迎指错。(学习C++。一本好书真的很重要,呵呵)
热心网友
时间:2024-10-28 06:50
你自己的答案错了因为两个反回值分别是return i*i; 和return 2*d;
除非你把他改成return i;和return d;
上面的调用其实是因为int 和long类型几乎一样,就是可以输出的字的长度多点好小点,而double和float也是和上面差不多的,所以调用时他们调用的都是相同的,如果cout<<print(a)<<endl<<print(b)<<endl<<print(d)<<endl<<print(l)<<endl;把他们写在一块就会出现每个函数先调用,接着运行
cout<<返回的值<<endl<<返回的值<<endl<<返回的值<<endl<<返回的值<<endl;
所以出现上面的答案,而用
cout<<print(a)<<endl;
cout<<print(b)<<endl;
cout<<print(d)<<endl;
cout<<print(l)<<endl;
把他们分开了就会第一个调用回来再直接输出,导致一个字母一个答案
热心网友
时间:2024-10-28 06:52
哦,明白你的意思了,输出确实是打印错了,
其实这是C++输出的问题,举个简单的例子,
比如a,b,c都是一个表达式;
那么cout<<a<<b<<c;
编译器会怎么处理呢?
它会先算出c表达式,再算出b表达式,最后算出a表达式,算完所有的结果后,在将三个值依次输出,(输出默认是从右向左进行的);
你上面的题目如果是
cout<<print(a)<<endl<<print(b)<<endl<<print(d)<<endl<<print(l)<<endl;
按照我上面说的,先进入函数print(l),此时输出了a,而l的平方被保存到一个类似栈的数据结构中,再进入print(d),此时输出了b,而d的平方也被保存到刚才的栈中,再进入print(b),此时输出了b,而b的平方也被保存到刚才的栈中,最后进入print(a),此时输出了a,而a的平方也被保存到刚才的栈中,此时已经输出了a b b a,最后输出函数将栈中保存的结果全部输出,就是25 9.2 3.3
而你的另外一种输出,是将cout函数一个一个做,就形成了那种结果
我觉得你可以将cout<<a<<b<<c当作一个函数a,b,c是它的三个参数
cout<<a<<b<<c;是将函数执行了依次
而cout<<a;cout<<b;cout<<c;是将函数做了三次
热心网友
时间:2024-10-28 06:48
首先,你自己把答案弄错了,正确答案是:
a
b
b
a
625
18.4
6.6
81
a
625
b
18.4
b
6.6
a
81
第一个输出语句,系统首先扫描整个表达式,先执行print(a),print(b)、print(d)和print(l)等,然后执行cout。
第二个及以后的输出语句则不同了,它是每个cout执行完后,再执行下一个cout语句。而在执行每个cout语句时,顺序和
上面的一样,所以就出现了上面的答案。
和输出拼接没有关系
建议看看相关资料或者MSDN
热心网友
时间:2024-10-28 06:51
这涉及到拼接输出的问题。
举例说明cout<<"abcd"<<"this is a girl.";就是一个输出拼接。
其在内存中的运行如下:
当调用cout时,先在内存中获得输出缓冲区,然后选取调用cout的对象("abcd","this is a girl.")依次将其放入输出缓冲区,待拼接语句中的对象全部进入到缓冲区以后,将他们输出到屏幕。
cout<<print(a)<<endl<<print(b)<<endl<<print(d)<<endl<<print(l)<<endl; 此句拼接输出时,相当于
cout<<625<<endl<<18.4<<endl<<6.6<<endl<<81<<endl;
虽然在print运行时输出了a,b,b,a;但是本句是在等待四个数值全部进入输出缓冲区后才将数字输出的。
楼下的,我只是说出了此句运行时与内存的关系,为什么会有先有后,或是一起输出。
----------------------------------------------------------------------
print是重载函数吧,当调用此函数时,首先判断参数类型,然后调用为该类型所定义的相应函数体。