【常见错误讨论帖_No.12_C++ 参数传递方式导致的对象切割问题】
时间:2011-12-04
来源:互联网
引用:
==【注意】==- m6 S/ r+ [7 n- ?) U5 V" B3 B' n程序语言只是我们与计算机交流并让计算机实现我们创造性思想的工具,可以并鼓励深入掌握一门语言,但千万别沉迷于钻某种语言的牛角尖,一定要把握好二者间的度
% k* h- D" @& J. d: F% ^本帖属不定时连载贴,以试卷的形式提出一个比较基础的问题供大家思考讨论,问题的解析将在下一更新贴中一并给出,这样做是希望还不清楚问题的朋友有自己思考和讨论的时间,希望大家能从这些帖子中有所收获。( l5 C7 ?) x0 {$ q
0 ~& R3 T9 U2 y! Z
贴中问题属我在学习C\C++过程中遇到的一些语法或者比较隐晦的程序问题,其中有自己的总结,也不乏网络上搜索到的经典解析,在此分享给大家,希望能起到抛砖引玉的作用9 p& [7 P1 ~( V, X+ h
: f9 m% M! p+ _1 z8 s. X6 }' g
我已认真检查过自己的帖子,但难免有疏忽,如大家在阅读过程中仍发现有问题,请及时通知,我会及时更正,以免误导大家,万分感谢^_^
) }) t5 [% C6 w5 j9 j: U& y; X f2 k, w2 W
/ Y$ Y3 O* l, O5 F+ ^& R& N% W
【No.12 C++ 参数传递方式导致的对象切割问题】$ _$ Q: m$ ?8 e* R
由于连载形式,每帖第二部分都配有上一问题的解答。为了保持帖子的针对性和一致性,此贴仅供交流讨论本次问题,若大家对上一问题有任何疑问,请通过解答末尾的传送链接前往该问题贴回复讨论
[问题12]1 ]* y5 @# A7 Z1 y& c' ~请写出以下代码的执行结果并说明原因:
, u3 O' F' W }: v; P* l
复制内容到剪贴板
class Base
{
public:
virtual void print(void) const { std::cout<<"Base::print()"<<std::endl; }
};
class Derived : public Base
{
public:
virtual void print(void) const { std::cout<<"Derived::print()"<<std::endl; }
};
void passByValue(Base obj)
{
obj.print();
}
void passByReferenceToConst(const Base& obj)
{
obj.print();
}
int main(int argc, char **argv)
{
Derived derived;
passByValue(derived);
passByReferenceToConst(derived);
return EXIT_SUCCESS;
}
问题浅析! Q& P* J. G; }- u代码:
#include<iostream>class Base
{
public:
virtual void print(void) const { std::cout<<"Base::print()"<<std::endl; }
};
class Derived : public Base
{
public:
virtual void print(void) const { std::cout<<"Derived::print()"<<std::endl; }
};
void passByValue(Base obj)
{
obj.print();
}
void passByReferenceToConst(const Base& obj)
{
obj.print();
}
int main(int argc, char **argv)
{
Derived derived;
passByValue(derived);
passByReferenceToConst(derived);
return EXIT_SUCCESS;
}
复制内容到剪贴板
*解决本问题的关键在于记住以下准则:
*① 我们可以为一个或多个形参指定默认实参
* 但是如果有一个形参被指定了默认实参,
* 那么,该形参后的所有形参都必须指定
* 默认实参。
*② 函数调用的实参按位置对形参进行替换
* 默认实参只能用来替换函数调用中缺少
* 的尾部实参。
************************************/
#include<iostream>
using namespace std;
void defaultArg(int a=24, int b=48, char c='c')
{
cout<<"a = "<<a<<endl;
cout<<"b = "<<b<<endl;
cout<<"c = "<<c<<endl;
cout<<endl;
}
int main(int argc, char **argv)
{
defaultArg();
//没有提供实参,因此本函数调用使用默认实
//参a=24,b=48,c='c'
defaultArg(1);
//有一个实参1,根据准则②,默认实参只能替换
//函数调用中缺少的尾部实参,所以a=1,b和c使用
//默认实参b=48,c='c'
defaultArg(1,2);
//同上,a=1,b=2,c='c'
defaultArg( , ,'A');
//编译错误,默认实参只能用来替换函数调用中缺少
//的尾部实参,这里试图用默认实参a=24,b=48来替换
//本函数调用时缺少的实参,编译错误
defaultArg('c');
//有一个实参'c',根据准则②,因此本函数调用的实
//参为a='c',b和c使用的是实参b=48,c='c'
return EXIT_SUCCESS;
}
代码:
/****解决本问题的关键在于记住以下准则:
*① 我们可以为一个或多个形参指定默认实参
* 但是如果有一个形参被指定了默认实参,
* 那么,该形参后的所有形参都必须指定
* 默认实参。
*② 函数调用的实参按位置对形参进行替换
* 默认实参只能用来替换函数调用中缺少
* 的尾部实参。
************************************/
#include<iostream>
using namespace std;
void defaultArg(int a=24, int b=48, char c='c')
{
cout<<"a = "<<a<<endl;
cout<<"b = "<<b<<endl;
cout<<"c = "<<c<<endl;
cout<<endl;
}
int main(int argc, char **argv)
{
defaultArg();
//没有提供实参,因此本函数调用使用默认实
//参a=24,b=48,c='c'
defaultArg(1);
//有一个实参1,根据准则②,默认实参只能替换
//函数调用中缺少的尾部实参,所以a=1,b和c使用
//默认实参b=48,c='c'
defaultArg(1,2);
//同上,a=1,b=2,c='c'
defaultArg( , ,'A');
//编译错误,默认实参只能用来替换函数调用中缺少
//的尾部实参,这里试图用默认实参a=24,b=48来替换
//本函数调用时缺少的实参,编译错误
defaultArg('c');
//有一个实参'c',根据准则②,因此本函数调用的实
//参为a='c',b和c使用的是实参b=48,c='c'
return EXIT_SUCCESS;
}
TIPs 如对本解析有任何疑问,请点我进入上一问题发帖讨论- V0 W/ e6 v' [; K: R( n; A
+ _3 B2 H9 c; t; A! y! f
* f8 K' [" k; I 神奇de传送门* {; }1 [6 D3 ^/ h* j. v7 N
/ ]; q: t+ e1 s" N! b; G6 V
Q; `2 c% q+ |0 V5 K
作者: Bill_Hoo 发布时间: 2011-12-04
复制内容到剪贴板
{
Derived derived;
passByValue(derived);//基类
passByReferenceToConst(derived);//派生类;引用——多态
return EXIT_SUCCESS;
}
代码:
int main(int argc, char **argv){
Derived derived;
passByValue(derived);//基类
passByReferenceToConst(derived);//派生类;引用——多态
return EXIT_SUCCESS;
}
作者: 月夜幻影 发布时间: 2011-12-05
相关阅读 更多
热门阅读
-
office 2019专业增强版最新2021版激活秘钥/序列号/激活码推荐 附激活工具
阅读:74
-
如何安装mysql8.0
阅读:31
-
Word快速设置标题样式步骤详解
阅读:28
-
20+道必知必会的Vue面试题(附答案解析)
阅读:37
-
HTML如何制作表单
阅读:22
-
百词斩可以改天数吗?当然可以,4个步骤轻松修改天数!
阅读:31
-
ET文件格式和XLS格式文件之间如何转化?
阅读:24
-
react和vue的区别及优缺点是什么
阅读:121
-
支付宝人脸识别如何关闭?
阅读:21
-
腾讯微云怎么修改照片或视频备份路径?
阅读:28