免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 2608 | 回复: 6
打印 上一主题 下一主题

[函数] 请教关于构造函数与拷贝构造函数匹配及调用原则 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2005-11-30 14:29 |只看该作者 |倒序浏览
代码1:
#include <iostream>
using namespace std;


class B
{
private:
    string m_val;
public:
    B(string val):m_val(val)
    {
                cout<<"Constructor "<<val.c_str()<<endl;
               
    };
   
        /*//拷贝构造1
        B(B& b):m_val(b.m_val)
    {
                cout<<"copy Constructor "<<b.m_val.c_str()<<endl;
    };
        //*/

        /*//拷贝构造2
    B(const B& b):m_val(b.m_val)
    {
                cout<<"const copy Constructor "<<b.m_val.c_str()<<endl;
    };
        //*/
    virtual ~B()
    {
                cout<<"Destructor "<<m_val.c_str()<<endl;
    };
    void Print()
    {
                cout<<m_val.c_str()<<endl;
    };
};

int main(int argc,char **argv){
        B b1=B("b1");
        B b2("b2");
}

WIN执行结果:
Constructor b1
Destructor b1
Constructor b2
Destructor b2
Destructor b1

LINUX执行结果
Constructor b1
Constructor b2
Destructor b2
Destructor b1



代码2:
#include <iostream>
using namespace std;


class B
{
private:
    string m_val;
public:
    B(string val):m_val(val)
    {
                cout<<"Constructor "<<val.c_str()<<endl;
               
    };
   
        //*//拷贝构造1
        B(B& b):m_val(b.m_val)
    {
                cout<<"copy Constructor "<<b.m_val.c_str()<<endl;
    };
        //*/

        /*//拷贝构造2
    B(const B& b):m_val(b.m_val)
    {
                cout<<"const copy Constructor "<<b.m_val.c_str()<<endl;
    };
        //*/
    virtual ~B()
    {
                cout<<"Destructor "<<m_val.c_str()<<endl;
    };
    void Print()
    {
                cout<<m_val.c_str()<<endl;
    };
};

int main(int argc,char **argv){
        B b1=B("b1");
        B b2("b2");
}

WIN执行结果
Constructor b1
copy Constructor b1
Destructor b1
Constructor b2
Destructor b2
Destructor b1

LINUX执行结果
编译不能通过,提示:
copyconstruct.cpp:40: no matching function for call to `B::B(B)'
copyconstruct.cpp:17: candidates are: B::B(B&)
copyconstruct.cpp:10:                 B::B(std::basic_string<char,
   std::char_traits<char>, std::allocator<char> >)

代码3:

#include <iostream>
using namespace std;


class B
{
private:
    string m_val;
public:
    B(string val):m_val(val)
    {
                cout<<"Constructor "<<val.c_str()<<endl;
               
    };
   
        //*//拷贝构造1
        B(B& b):m_val(b.m_val)
    {
                cout<<"copy Constructor "<<b.m_val.c_str()<<endl;
    };
        //*/

        //*//拷贝构造2
    B(const B& b):m_val(b.m_val)
    {
                cout<<"const copy Constructor "<<b.m_val.c_str()<<endl;
    };
        //*/
    virtual ~B()
    {
                cout<<"Destructor "<<m_val.c_str()<<endl;
    };
    void Print()
    {
                cout<<m_val.c_str()<<endl;
    };
};

int main(int argc,char **argv){
        B b1=B("b1");
        B b2("b2");
}

WIN执行结果:
Constructor b1
copy Constructor b1
Destructor b1
Constructor b2
Destructor b2
Destructor b1

LINUX执行结果:
Constructor b1
Constructor b2
Destructor b2
Destructor b1


不能理解,为什么代码2在LINUX(g++ 3.2.2)下不能通过,在WIN(VC)下能通过?
为什么代码3在LINUX下能通过,如果代码2是找不到匹配构造函数,添加了代码3提供的拷贝构造2通过了,那为什么在代码3执行时确未调用拷贝构造2?
代码2调用不能通过的原因是由于出现了B("b1");这样的构造调用引起的,而B b1("b1"),则不会引起,两者的差别是什么呢?而且从代码的调用看也并未看出对构造函数调用的差异,但为什么会引起编译的差异呢?

我的猜测+理解是形如B("b1");必须要求匹配一个拷贝构造,而因为代码1中有缺省的拷贝构造,因此调用缺省的拷贝构造,而在代码2中提供了拷贝构造,但确不匹配,所以LINUX下不能编译通过,代码3中提供了匹配的拷贝构造,因此能构通过,但是有个疑团是既然拷贝构造2提供了且唯一提供了但为何没见调用?这里是不是还掺入了一个类型转换的问题?疑问颇多,一头雾水!

论坛徽章:
0
2 [报告]
发表于 2005-11-30 14:52 |只看该作者
对象(对象) 是拷贝构造!  对象=对象 是运算符重载!
类(对象) 是无对象拷贝!也是可行的!但无对象只能当赋值,可以理解为常量!
 
以上问题,可能是编译器对拷贝备份处理不同!

论坛徽章:
0
3 [报告]
发表于 2005-11-30 14:54 |只看该作者
  1.    
  2.      B(B& b):m_val(b.m_val)
  3.     {
  4.                 cout<<"copy Constructor "<<b.m_val.c_str()<<endl;
  5.     };
  6.         //*/

  7.         /*//拷贝构造2
  8.     B(const B& b):m_val(b.m_val)
  9.     {
  10.                 cout<<"const copy Constructor "<<b.m_val.c_str()<<endl;
  11.     };
复制代码


为什么要提供两个版本的拷贝构造函数呢?

难道你的构造函数要对被拷贝方的状态进行修改吗?
你先把多余的那个去掉,在把结果贴出来。

通常情况下,B("b1")这种形式,编译器会首先调用string("b1"),然后调用B(string), 接着调用B(const  B&);编译器是用的是"一步推导"的策略.

论坛徽章:
0
4 [报告]
发表于 2005-11-30 15:19 |只看该作者

回复 3楼 renstone921 的帖子

不是要提供两个版本的拷贝构造函数,而是最初在没有拷贝构造2出现了问题,所以添加了拷贝构造2,当然拷贝构造1不把参数定义为const是有失偏颇,但现在疑问在于为什么在这里会出现编译错呢?

论坛徽章:
0
5 [报告]
发表于 2005-11-30 15:31 |只看该作者
candidate就是候选者的意思。

B("b1")这种形式,编译器会首先调用string("b1"),然后调用B(string), 接着调用B(const  B&)还是调用B(B&), 你给他提供了两种选择,这两种都可以用,但编译器不知道到底用那个.

写代码不仅要注意语法层次,也要注意语意层次。

论坛徽章:
0
6 [报告]
发表于 2005-11-30 15:33 |只看该作者
结果上   看,不如加explict来约束,这样就可以控制了,其他的东西和编译器相关会有问题

论坛徽章:
0
7 [报告]
发表于 2005-12-01 17:02 |只看该作者
const是不能用来区分重载的,都是精确匹配
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP