标题:转换构造函数 引发的二义性
只看楼主
hzz063
Rank: 3Rank: 3
来 自:横县百合
等 级:论坛游侠
帖 子:80
专家分:114
注 册:2010-1-27
结帖率:100%
 问题点数:0 回复次数:7 
转换构造函数 引发的二义性


问题是关于转换构造函数的调用,
比如说类 complex 中定义了转换构造函数,把 int参数转换成complex类的对象。
complex c1;
complex c2;
有表达式:
        c1 = c2 + 10;
书上给我的感觉是说,他会隐式去调用 complex(10)这个转换构造函数,但我在vc6上是
通不过的,当然 c1 = c2 + complex(10)显式调用是可以的。


正因为这样又引出了另一个问题,一个类里面有 构造函数、 类型转换函数、 运算符 + 重载函数。
书上说像这样的代码编译会出错,原因时出现二义性,就是它不懂时调用转换构造函数,把55变成date类对象,
还是调用 类性转换函数,把 da 转换成int类型。
恩,听起来很有道理........

程序代码:
#include <iostream.h>

class date
{
public:
    date(int a, int b);
    date(int n);                              //转换构造函数
       operator int();                             //类型转换函数
    friend date  operator+(date &, date &);   //重载 +
    void output(void);

private:
    int  str;
    int  mimg;
};


/****** 定义 ******/
date::date(int a, int b)  //构造函数
{ str = a;
  mimg = b;
}

date :: date(int n)      //转换构造函数
{
    str = n;
    mimg = 0;
}

date::operator int()   //类型转换函数
{
  return str;
}


date  operator +(date &a, date &b) //重载 +
{
    return date(a.str + b.str, a.mimg + b.mimg);
}

void date::output(void)
{
    cout << str << "  " << mimg << endl;
    return;
}
/////////////////////////////////////////////



int main(void)
{ 

   date da(100, 200);

 
   date c(0,0);

   c = 55 + da;

   c.output();

    return 0;
}

但问题是,我能编译通过.....
我的理解是: 正是因为它不能 隐式 调用【 转换构造函数】 date(55),所以去调用了【 类型转换函数】 operator int(),把 da 转成int了,
结果变成 c = 55 +100   ,这里就调用【 转换构造函数】
当然最后输出的也是 155 0

不知是不是我理解不到位,,书上说这样的代码有二义性,
不知道问题在那里....

搜索更多相关主题的帖子: 函数 构造 
2010-07-15 11:36
最近不在
Rank: 8Rank: 8
等 级:蝙蝠侠
威 望:5
帖 子:204
专家分:842
注 册:2010-2-28
得分:0 
问题1,由于没有重载+;
问题2。+重载形参没加const修饰符。因为常量(10)的引用无法赋给非const型的引用做形参。导致无法调用operator +,所以就只能调用类型重载了;不太好表达,见谅。
请看代码:
程序代码:
// Note:Your choice is C++ IDE
#include <iostream>
using namespace std;

class A
{
public:
    A(int n = 0);
    //explicit A(int n = 0); //关掉隐式类型转换可能需要用到手动提供的=重载(包括对象赋值和int赋值)
    ~A();
   
    operator int ()
    {
        return m_n;
    }
   
    const A& operator = (const int& n);
    const A& operator = (const A& t);
   
    friend A operator + (const A &n1, const A &n2);
   
private:
    int m_n;
};

A::A(int n)
{
    m_n = n;
}

A::~A()
{
   
}

A operator + (const A &n1, const A &n2)
{   
    return A(n1.m_n + n2.m_n);
}

const A& A::operator = (const int& n)
{
    cout<<"int ="<<endl;
    m_n = n;
    return *this;
}

const A& A::operator = (const A& t)
{
    cout<<"A ="<<endl;
    m_n = t.m_n;
    return *this;
}

int main()
{
      A obj(10);
      A obj1(25);
      A obj2;
     
      //错误做法
      //obj2 = obj1 + 10; 造成2异性,2种方法都符合,编译器不知道选择谁
      //看过程
      //A ATemp = 10; A obj2 = obj1 + Atemp;
      //A obj2 = obj1.operator int() + 10; A Atemp = obj1.operator int() + 10; obj2 = ATemp;
     
      //正确做法。显示调用指定方法.下面2种方法都可以
      //obj2 = operator + (obj1, 10); 关掉隐式构造,10需要变为显示构造A(10)或通过临时对象完成。
      //obj2 = obj1.operator int() + 10;
    return 0;
}

 
2010-07-15 14:36
hzz063
Rank: 3Rank: 3
来 自:横县百合
等 级:论坛游侠
帖 子:80
专家分:114
注 册:2010-1-27
得分:0 
恩,我看了代码.还是不怎么理解...
说第一个问题,,
程序代码:
#include <iostream.h>


class date
{
public:
       
    date(int a, int b);
    date(int a);                              
    friend date operator+( date &a,  date &b); //这里用引用的话,编译出错,如果改为 friend date operator+( date a,  date b);
    void output(void);                        // 不用引用,可以通过。
private:
    int i;
    int j;
};

/*  */
date::date(int a, int b)
{
    i = a; j = b;
}

date::date(int a)
{
    i = a; j = 0;
}

date operator+(date &a, date &b)
{
    return date(a.i + b.i, a.j + b.j);
}


void date::output(void)
{
    cout << i << "  " << j << endl;
    return;
}


int main(void)
{

    date da(100, 200);
    date c(0,0);
    c = 10 + da;

    c.output();

    return 0;
}
这两种写法怎么理解呀,,

一切只因为喜欢。
2010-07-15 20:47
最近不在
Rank: 8Rank: 8
等 级:蝙蝠侠
威 望:5
帖 子:204
专家分:842
注 册:2010-2-28
得分:0 
程序代码:
// Note:Your choice is C++ IDE
#include <iostream>
using namespace std;

void fun(int &n)
{
   
}

void fun1(const int &n)
{
   
}

void fun2(const int n)  //写成这种实际意义不大,都是对副本进行操作。
{
   
}

void fun3(int n)
{
   
}

//要弄懂要引用传递和按值传递。
//const引用和非const引用初始化的区别。
int main()
{
    int n = 10;
    const int &n1 = n; 
   
    const int m = 10;
    //int &m1 = m;  错误
   
      //fun(10);  报错.按引用传递就是对参数直接操作。所以将10传给一个非const型是通不过的
      fun1(10);  //这个正确
      //int n = 10;
      fun(n);
     
      fun3(10);   //非引用做形参,都要创建副本保存参数的值,再对副本进行操作。 
      fun2(10);
    return 0;
}
2010-07-15 23:17
hzz063
Rank: 3Rank: 3
来 自:横县百合
等 级:论坛游侠
帖 子:80
专家分:114
注 册:2010-1-27
得分:0 
非常非常感谢你!!!
这里:
   
 //fun(10);  报错.按引用传递就是对参数直接操作。所以将10传给一个非const型是通不过的
我明白了...10是常量,如果改成变量 n 没问题。
但....也许我脑袋实在时不行...
但这与上一个例子有什么共同之处?
friend date operator+( date &a,  date &b);
如果是“因为常量(10)的引用无法赋给非const型的引用做形参。”的话,
那么把 10 放入变量 n 中,然后再  c = n + da; 应该来说来是可以过呀,
但实际还是不能。

E:\练习文件\【C++】\练习2.cpp(47) : error C2678: binary '+' : no operator defined which takes a left-hand operand of type 'int' (or there is no acceptable conversion)
执行 cl.exe 时出错.

实在时麻烦你了.....

一切只因为喜欢。
2010-07-16 20:20
lintaoyn
Rank: 11Rank: 11Rank: 11Rank: 11
等 级:小飞侠
威 望:4
帖 子:605
专家分:2489
注 册:2009-4-8
得分:0 
非const的引用只能绑定同类型的对象,const则可以绑定能互相转换的类型。
int a = 0;
double &b = a;//error
const double &c = a;//ok
你可以去看下C++ primer里引用的那节

迭代的是人,递归的是神。
2010-07-16 21:10
hzz063
Rank: 3Rank: 3
来 自:横县百合
等 级:论坛游侠
帖 子:80
专家分:114
注 册:2010-1-27
得分:0 
回复 6楼 lintaoyn
恩,说到点上了…隐式转换不会被用于非const的引用参数。

一切只因为喜欢。
2010-07-17 08:55



参与讨论请移步原网站贴子:https://bbs.bccn.net/thread-313040-1-1.html




关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.385355 second(s), 7 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved