关于友元和复制构造函数的调用

ftkghost 2004-10-09 05:37:29
/* 类中的friend关键词指出,另一个类的特定函数或所有成员函数
*可以读写该类的私用数据成员.使得类得以保持私用实现,同时允许
*特定的类和函数有控制的访问该实现.
*/

#include<iostream>

//A forward reference. 前置引用,告诉编译器以后声明class Date.
//class Date; 为什么前置引用在Dev-C++中不能编译通过,而在VC6中可以?

class CustomDate{
int da,yr;
public:
CustomDate(int d=0,int y=0):da(d),yr(y)
{}
CustomDate(CustomDate& cd)
{
da=cd.da;
yr=cd.yr;
std::cout<<"调用CustomDate的复制构造函数"<<std::endl;
}
void display() const
{
std::cout<<yr<<'-'<<da<<std::endl;
}
//Allow Date member functions to
//see customDate private members.
friend class Date; //在 Dev-C++中前置引用不能通过编译,这种声明叫做显式友元前向引用(编译通过)
};

class Date{
int mo,da,yr;
public:
Date(int m=6,int d=20,int y=1984):mo(m),da(d),yr(y)
{}
operator CustomDate();
};
//Member conversion function (Date->CustomDate).
Date::operator CustomDate()
{
static int dys[]={31,28,31,30,31,30,31,31,30,31,30,31};
CustomDate cd(0,yr);
for(int i=0;i<mo-1;i++)
cd.da+=dys[i]; //CustomDate的da是private数据成员,但是由于在CustomDate中
cd.da+=da; //声明了Date作为其友元,因此其私有成员在Date中可见。
std::cout<<"调用Date的成员转换函数"<<std::endl;
return cd;
}

int main()
{
Date dt(3,13,1984);
CustomDate cd;
cd=dt; //VC6中两次调用CustomDate的复制构造函数
cd.display(); //而在Dev-C++中不调用CustomDate的复制构造函数
system("Pause");
return 0;
}

问题1: 为什么前置引用在Dev-C++中不能编译通过,而在VC6中可以?
问题2: 为什么在在VC中两次调用CustomDate的复制构造函数,而在Dev-C++中一次也没有调用?

...全文
174 12 打赏 收藏 转发到动态 举报
写回复
用AI写文章
12 条回复
切换为时间正序
请发表友善的回复…
发表回复
248406869 2004-10-14
  • 打赏
  • 举报
回复
我的vc6只调用了一次拷贝构造函数。我想正向楼上说的return时调用的。cd=dt这个等号调用的不是拷贝构造函数,只有在初始化语句中才调用拷贝构造函数,它调用=操作符,所以dev c++没有调用拷贝构造函数。
ftkghost 2004-10-14
  • 打赏
  • 举报
回复
o 谢谢各位阿
ftkghost 2004-10-13
  • 打赏
  • 举报
回复
没完全解决,顶一下
ZKYcomputer 2004-10-09
  • 打赏
  • 举报
回复
cd=dt; //VC6中两次调用CustomDate的复制构造函数

为什么啊???
anonym 2004-10-09
  • 打赏
  • 举报
回复
sorry,上边有一笔误,应为:g++编译结果只调用了Date::operator CustomDate()
//错误:"而在g++中,只有CustomDate(CustomDate& cd)被调用 " :-)
anonym 2004-10-09
  • 打赏
  • 举报
回复
用这段代码可以测试一下
#include <iostream>

class A{
public:
A(){
std::cout << "A::A()" << std::endl;
}
A(A& a){
std::cout << "A::A(A& a)" << std::endl;
}
A& operator=(const A& a){
std::cout << "A::operator=(const A& a)" <<std::endl;
return *this;
}
~A(){
std::cout << "A::~A()" << std::endl;
}
};

A foo(){
A a;
return a;
};

int main(){
A a;
std::cout << "Start Foo()" << std::endl;
a = foo();
std::cout << "End Foo()" << std::endl;
return 0;
}
VC7.1结果
A::A()
Start Foo()
A::A()
A::A(A& a)
A::~A()
A::operator=(const A& a)
A::~A()
End Foo()
A::~A()
而使用mingw-g++ 3.23 结果如下
A::A()
Start Foo()
A::A()
A::operator=(const A& a)
A::~A()
End Foo()
A::~A()

anonym 2004-10-09
  • 打赏
  • 举报
回复
在VC中先调用类型转换函数,然后调用拷贝构造函数。这可以理解,因为cd=dt句首先调用Date::operator CustomDate(),而这个函数最后要返回一个CustomDate因此
CustomDate(CustomDate& cd)被调用。
而在g++中,只有CustomDate(CustomDate& cd)被调用,因为g++中在函数中返回对象时并不调用拷贝构造函数,而是保存局部变量直到使用完才销毁该局部对象。
ftkghost 2004-10-09
  • 打赏
  • 举报
回复
我的Dev-C++是4.9.8.0版本的
sharkhuang 2004-10-09
  • 打赏
  • 举报
回复
能编译通过。

cd.display(); //而在Dev-C++中不调用CustomDate的复制构造函数
为啥要调用?
newegg2002 2004-10-09
  • 打赏
  • 举报
回复
细心聆听ing....
短歌如风 2004-10-09
  • 打赏
  • 举报
回复
不对啊,没有优化也不应该调用两次,应该是一次,赋值时调用的是拷贝赋值操作符。
短歌如风 2004-10-09
  • 打赏
  • 举报
回复
在Dev C++ 4.9.9.0中:
1:无论是否有class Date;这一句都可以编译
2:没有调用构造函数是因为被优化掉了——返回值一次,赋值一次。你可以同时监视一下CustomDate的析构函数,只要与构造函数匹配就说明是正确的——无论调用了多少次。不过监视析构函数要把除system一句外的其它语句放到另一个函数中去,再让main去调用。同时要注意还有一次缺少构造的调用不要忽略了。

64,648

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧