关于函数参数类型隐式转换与子类类型问题,我与vs2003编译器的理解不同

freezingfire 2007-08-28 10:31:45
先看下源代码,函数内容不用管,骗编译器的,只看接口。

编译环境:VS2003 7.1.3088

class A
{
};

class B
{
public:
operator A*() { return NULL; };
};

class C
{
public:
operator B() { B b; return b; };
};

class D : public A
{
};

class E
{
public:
operator D*() { return NULL; };
};

class F
{
public:
operator D() { D d; return d; };
};

void foo1(A* a) {};

void foo3(A a) {};

int main()
{
B b;
C c;
E e;
F f;

foo1(b); // 1
foo1(c); // 2

foo1(e); // 3
foo3(f); // 4

return 0;
}

首先,我知道的原则,编译器在匹配函数参数时,不会为你做2次隐式转换(记不清确切术语了,请原谅),因此,上面注释1的地方可以成功,注释2的地方会编译失败。这个没问题。

但是对于3和4,我就比较惊讶,特别是4。

对于3来说,存在隐式转换将e变成D*类型,但是foo1要求的是A*。 这个能编译通过,我姑且算作子类指针永远可以看成父类指针,因此不需要转换。

但是对于4来说,将f转换成D类型,居然就可以直接匹配A类型?

也许我对继承的理解有误?继承下来的子类,不必作任何转换就可以看作父类类型?这么说倒是也很合逻辑。。。

企盼达人解惑。
...全文
537 19 打赏 收藏 转发到动态 举报
写回复
用AI写文章
19 条回复
切换为时间正序
请发表友善的回复…
发表回复
mgtcllxl 2007-08-30
  • 打赏
  • 举报
回复
首先,我知道的原则,编译器在匹配函数参数时,不会为你做2次隐式转换
===
这句话的确有问题,原句是什么呢
iatsbg 2007-08-29
  • 打赏
  • 举报
回复
ISO C++ Standard (ISO14882) 2003.pdf里找的。

12.3 P192

At most one user-defined conversion (constructor or conversion function) is implicitly applied to a single
value.

下面包含User-defined conversion的定义:

Type conversions of class objects can be specified by constructors and by conversion functions. These conversions
are called user-defined conversions and are used for implicit type conversions (clause 4), for
initialization (8.5), and for explicit type conversions (5.4, 5.2.9).

由此可见,子类到基类的转换不算user-defined conversion,所以只进行了一次user-defined conversion。
星羽 2007-08-29
  • 打赏
  • 举报
回复
对于3来说,存在隐式转换将e变成D*类型,但是foo1要求的是A*。 这个能编译通过,我姑且算作子类指针永远可以看成父类指针,因此不需要转换。

---------

这个本来派生,多态就是这样,派生类指针永远是基类指针





struct base
{
int n1;
int n2;
int n3;
int n4;
};

struct derive : public base
{

};

void fun(base s)
{

}

int main(void)
{
derive d;
fun(d);

}

这个是能编过运行,所以你的 4 也就没问题


这并没有2次转换,而是直接把派生类截取到基类

看看asm就知道了


jixingzhong 2007-08-29
  • 打赏
  • 举报
回复
也许我对继承的理解有误?继承下来的子类,不必作任何转换就可以看作父类类型?
===========
可以这么认为,
这个转换其实是一个 对象截取,
总是可以从一个 子类对象中 截取出父类子对象的。
goodluckyxl 2007-08-29
  • 打赏
  • 举报
回复
父类到子类转换应该是永远可以进行 不是implict而是同一种类型父类型

3 4的只完成一次转换由E F-> D 也就是 A的转化
starnight1981 2007-08-29
  • 打赏
  • 举报
回复
现有芳城园(方庄家乐福附近)小区四居中的一居出租,面积大概12平方米。

屋内有单独电视。洗衣机、冰箱、微波炉等家电公用。洗澡、做饭均可。

如有意者,请来电。

租金:800/月 付2押1

联系电话:13810345444 13466336212

中介勿扰
linux_is_perfect 2007-08-29
  • 打赏
  • 举报
回复
4是对象的切片, Thinking in C++里面有的
就算f可以转换成a, 你这个对象的大小都是1, 所以可以, 不过这很不安全
以后千万别这样用!!!

继承的隐式转换还有overload and override, 这也不是很容易搞清楚
C++高质量编程里面有

大家一起努力学习...
taodm 2007-08-29
  • 打赏
  • 举报
回复
去看《C++ Primer》3e P649
章节:对用户定义的转换序列划分等级
QQR_007 2007-08-29
  • 打赏
  • 举报
回复
学习 , 学习,
gfxiang 2007-08-29
  • 打赏
  • 举报
回复
我知道的原则,编译器在匹配函数参数时,不会为你做2次隐式转换(记不清确切术语了,请原谅)
=========
这句话似乎有点问题

class A
{
public:
A() { }
A(double d) { }
operator double() { }
};

void f(A a) { }
void g(int i) { }

int main()
{
int i;
f(i); // int->double, double->A

A a;
g(a); // A->double, double->int

return 0;
}
iatsbg 2007-08-29
  • 打赏
  • 举报
回复
但总体趋势是向标准靠拢啊~有些问题搞清楚还是有好处的。
xsh525 2007-08-29
  • 打赏
  • 举报
回复
我觉得没必要深究的,各个编译器对C++的标准实现是不一样的,有的没有完全支持标准,有的还擅自做了扩展
freezingfire 2007-08-29
  • 打赏
  • 举报
回复
我不同意gfxiang(afu)的说法。如果涉及到调用拷贝构造函数,那么必定被算作一次转换,则必定不会成功(因为调用拷贝构造函数是第二次转换了)。
goodluckyxl 2007-08-29
  • 打赏
  • 举报
回复
make a conclusion:
implicit conversion occurs with its constructor or operator type conversation functions.
when convert base-class into child-class, it don't fulfill both of conditions.
gfxiang 2007-08-28
  • 打赏
  • 举报
回复
class A
{
public:
virtual void print() { cout << "A::print()" << endl; }
};

class B: public A
{
public:
virtual void print() { cout << "B::print()" << endl; }
};

void f(A a)
{
a.print(); // 调用 A::print()
}

int main()
{
B b;
f(b); // 这里传参时调用了(编译器提供的)拷贝构造函数
return 0;
}

如果要定义拷贝构造函数,比如上面类A
A::A(const A& a)
{
// 这里的a时一个指向基类的引用,当然a也可以指向子类(和指针一样),所以子类是可以直接用来构造基类的
// ...
}
cnvb 2007-08-28
  • 打赏
  • 举报
回复
能想出这种例子...难为楼主了...盼大鸟横空出现...
gfxiang 2007-08-28
  • 打赏
  • 举报
回复
foo1(b); // 1 B::operator A*()
foo1(c); // 2 error

foo1(e); // 3 E::operator D*(),指向子类的指针是可以直接赋给指向基类的指针
foo3(f); // 4 E::operator D(),子类赋给基类,这里会调用拷贝构造函数,会slice子类,只把它当作基类看待
freezingfire 2007-08-28
  • 打赏
  • 举报
回复
各位能否给出具体书籍,文件上的引用?非常感谢。
iatsbg 2007-08-28
  • 打赏
  • 举报
回复
“继承下来的子类,不必作任何转换就可以看作父类类型”这是真的(public继承)。

64,686

社区成员

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

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