请教下派生类对象强制转换为基类对象,会不会有临时对象产生?如果有,为什么?

zhousitiaoda 2014-05-22 02:50:02
原帖地址http://bbs.csdn.net/topics/390793860,为了方便还是把示例代码贴下吧

class FBase
{

public:
virtual void Set()
{
info = _T("FBase");
}

void PrintInfo()
{
_tprintf(_T("%s\n"), info);
}

protected:
TCHAR *info;
};


class FChild : public FBase
{
public:
void Set()
{
info = _T("FChild");
}

};



FChild child;
child.Set();
child.PrintInfo();
((FBase)child).Set();
child.PrintInfo();

结果是打印2次“FChild”。(FBase)child这句貌似有临时对象产生,但如果有的话却并没有调用到构造函数,如果没有的话下面这几个值都不相同,指针之间的转换还能看懂,对象间的强制转换有点不太明白这个转换过程发生了些什么,求指点。

FBase* pBase = (FBase*)&child;
FBase* pBase2 = &(FBase)child;
FBase* pBase3 = &(FBase)child;
...全文
319 17 打赏 收藏 转发到动态 举报
写回复
用AI写文章
17 条回复
切换为时间正序
请发表友善的回复…
发表回复
friendbkf 2015-05-22
  • 打赏
  • 举报
回复
对于C风格的强制转换,以下两种方式的效果是一样的。 (T)expression //将expression转型为T类型 T(expression) //将expression转型为T类型 对于楼主的(FBase)child这样的强制转换,可以完全等同于 FBase(child) 这样再看的话,是不是就很清楚了。 临时变量生成了,发生了slicing! 再补充一句,使用static_cast<T>(child)将产生同样的效果,即也会生成临时基类变量。
zhousitiaoda 2014-05-26
  • 打赏
  • 举报
回复
引用 15 楼 ri_aje 的回复:
这句 (FBase)child 叫 explicit type conversion (cast notation)。 标准 5.4 定义了其行为,对主楼的用例,该语句等同与 static_cast<FBase>(child),后者的行为在 5.2.9/4 定义: Otherwise, an expression e can be explicitly converted to a type T using a static_cast of the form static_cast<T>(e) if the declaration T t(e); is well-formed, for some invented temporary variable t (8.5). The effect of such an explicit conversion is the same as performing the declaration and initialization and then using the temporary variable as the result of the conversion. The expression e is used as a glvalue if and only if the initialization uses it as a glvalue. 所以 ((FBase)child).Set(); 就是

FBase e(child); // copy construction
e.Set();
第一句就是复制构造发生的点。
多谢指点。。
ri_aje 2014-05-25
  • 打赏
  • 举报
回复
这句 (FBase)child 叫 explicit type conversion (cast notation)。 标准 5.4 定义了其行为,对主楼的用例,该语句等同与 static_cast<FBase>(child),后者的行为在 5.2.9/4 定义: Otherwise, an expression e can be explicitly converted to a type T using a static_cast of the form static_cast<T>(e) if the declaration T t(e); is well-formed, for some invented temporary variable t (8.5). The effect of such an explicit conversion is the same as performing the declaration and initialization and then using the temporary variable as the result of the conversion. The expression e is used as a glvalue if and only if the initialization uses it as a glvalue. 所以 ((FBase)child).Set(); 就是

FBase e(child); // copy construction
e.Set();
第一句就是复制构造发生的点。
zhousitiaoda 2014-05-23
  • 打赏
  • 举报
回复
引用 12 楼 shenchenman 的回复:
这种未命名的对象通常在三种条件下产生:为了使函数成功调用而进行隐式类型转换时候、传递函数参数和函数返回对象时候。 [
可是这里的强制转换不属于这3种条件的任何一种。
zhousitiaoda 2014-05-23
  • 打赏
  • 举报
回复
感谢2位的回答,过几天再结,看还有没有不同的意见的。
shenchenman 2014-05-22
  • 打赏
  • 举报
回复
引用 10 楼 zhousitiaoda 的回复:
[quote=引用 8 楼 Fire_Lord 的回复:] [quote=引用 6 楼 zhousitiaoda 的回复:] 多谢,额,我的意思并不是说为什么调用的是拷贝构造而不是构造,我想问的是为什么这种转换会有对象的生成。
因为这属于强制类型转换,而不是多太用到的引用或指针的转换。 就像 (int)123.01f[/quote] 你的意思是说,这种强制转换不管是内置类型还是class类型,都会伴随着临时对象的生成?[/quote] 你指的内置类型
引用 10 楼 zhousitiaoda 的回复:
[quote=引用 8 楼 Fire_Lord 的回复:] [quote=引用 6 楼 zhousitiaoda 的回复:] 多谢,额,我的意思并不是说为什么调用的是拷贝构造而不是构造,我想问的是为什么这种转换会有对象的生成。
因为这属于强制类型转换,而不是多太用到的引用或指针的转换。 就像 (int)123.01f[/quote] 你的意思是说,这种强制转换不管是内置类型还是class类型,都会伴随着临时对象的生成?[/quote] 不是。 临时对象建立一个没有命名的非堆对象会产生临时对象。这种未命名的对象通常在三种条件下产生:为了使函数成功调用而进行隐式类型转换时候、传递函数参数和函数返回对象时候。 临时对象是代码中看不到的,但是实际程序中确实存在的对象。临时对象是可以被编译器感知的。 内置类型不存在对象,只是变量
Fire_Lord 2014-05-22
  • 打赏
  • 举报
回复
引用 10 楼 zhousitiaoda 的回复:
[quote=引用 8 楼 Fire_Lord 的回复:] [quote=引用 6 楼 zhousitiaoda 的回复:] 多谢,额,我的意思并不是说为什么调用的是拷贝构造而不是构造,我想问的是为什么这种转换会有对象的生成。
因为这属于强制类型转换,而不是多太用到的引用或指针的转换。 就像 (int)123.01f[/quote] 你的意思是说,这种强制转换不管是内置类型还是class类型,都会伴随着临时对象的生成?[/quote] 对
zhousitiaoda 2014-05-22
  • 打赏
  • 举报
回复
引用 8 楼 Fire_Lord 的回复:
[quote=引用 6 楼 zhousitiaoda 的回复:] 多谢,额,我的意思并不是说为什么调用的是拷贝构造而不是构造,我想问的是为什么这种转换会有对象的生成。
因为这属于强制类型转换,而不是多太用到的引用或指针的转换。 就像 (int)123.01f[/quote] 你的意思是说,这种强制转换不管是内置类型还是class类型,都会伴随着临时对象的生成?
shenchenman 2014-05-22
  • 打赏
  • 举报
回复
引用 7 楼 zhousitiaoda 的回复:
[quote=引用 5 楼 shenchenman 的回复:] 1 (FBase)child 肯定产生了临时对象,通过拷贝构造 2 ((FBase)child).Set();这句没有意义,因为这是对临时对象的操作,不会影响child 3 FBase* pBase = (FBase*)&child;是多态 4 FBase* pBase2 = &(FBase)child;是把一个临时FBase对象的指针赋值给pBase2
肯定产生了临时对象 请教下为什么会产生[/quote] 既然有类型转换,当然会产生一个对应转换后型的对象,以供拷贝或其他操作。
Fire_Lord 2014-05-22
  • 打赏
  • 举报
回复
引用 6 楼 zhousitiaoda 的回复:
多谢,额,我的意思并不是说为什么调用的是拷贝构造而不是构造,我想问的是为什么这种转换会有对象的生成。
因为这属于强制类型转换,而不是多太用到的引用或指针的转换。 就像 (int)123.01f
zhousitiaoda 2014-05-22
  • 打赏
  • 举报
回复
引用 5 楼 shenchenman 的回复:
1 (FBase)child 肯定产生了临时对象,通过拷贝构造 2 ((FBase)child).Set();这句没有意义,因为这是对临时对象的操作,不会影响child 3 FBase* pBase = (FBase*)&child;是多态 4 FBase* pBase2 = &(FBase)child;是把一个临时FBase对象的指针赋值给pBase2
肯定产生了临时对象 请教下为什么会产生
zhousitiaoda 2014-05-22
  • 打赏
  • 举报
回复
多谢,额,我的意思并不是说为什么调用的是拷贝构造而不是构造,我想问的是为什么这种转换会有对象的生成。
shenchenman 2014-05-22
  • 打赏
  • 举报
回复
1 (FBase)child 肯定产生了临时对象,通过拷贝构造 2 ((FBase)child).Set();这句没有意义,因为这是对临时对象的操作,不会影响child 3 FBase* pBase = (FBase*)&child;是多态 4 FBase* pBase2 = &(FBase)child;是把一个临时FBase对象的指针赋值给pBase2
Fire_Lord 2014-05-22
  • 打赏
  • 举报
回复
引用 3 楼 zhousitiaoda 的回复:
[quote=引用 2 楼 Fire_Lord 的回复:] [/code]
感谢,(FBase)child 按照你说的应该是用child的基类部分拷贝构造一个匿名的FBase对象,可是还是不太明白这种转换为什么会有拷贝构造的调用,是标准有规定吗[/quote] 根据不同的场景调用不同的构造函数:


using namespace std;

class TestClass
{
public:
	TestClass(){ cout << "constructor..." << endl; }

	TestClass(TestClass& b) { cout << "copy constructor..." << endl;}

	TestClass& operator = (const TestClass& b) 
	{ cout << "assignment constructor..." << endl; return *this;}
};

void TestFunc(TestClass c){}

int _tmain(int argc, _TCHAR* argv[])
{
	//调用一般的构造函数
	TestClass obj1;			//constructor

	//创建对象并初始化,调用拷贝构造函数
	TestClass Obj2(obj1);	//copy constructor
	TestClass Obj3 = obj1;	//copy constructor

	//传递参数,产生临时变量,调用拷贝构造函数
	TestFunc(obj1);			//copy constructor

	//赋值操作,调用赋值构造函数
	Obj3 = Obj2;			//assignment constructor

	return 0;
}


zhousitiaoda 2014-05-22
  • 打赏
  • 举报
回复
引用 2 楼 Fire_Lord 的回复:
[/code]
感谢,(FBase)child 按照你说的应该是用child的基类部分拷贝构造一个匿名的FBase对象,可是还是不太明白这种转换为什么会有拷贝构造的调用,是标准有规定吗
Fire_Lord 2014-05-22
  • 打赏
  • 举报
回复
直接使用 (FBase)child 这种对象的转换是有临时对象产生的,调用的不是构造函数,而是拷贝构造函数

FBase(const FBase& b)
{
    //Copy Constructor code...
}
在使用多态的时候不能使用这种对象的强制转换,而应该使用指针或者引用(楼主肯定知道^^)。如果非要深究,应该是这么回事:

        FChild    child;
	child.Set();
	child.PrintInfo();	//print: FChild

	//对对象进行类型转换,调用默认的拷贝构造函数进行浅拷贝
	//此时b.info 指向 child.info 内存地址
	// b.vtable 指向 FBase::vtable
 	FBase b = (FBase)child;
	b.PrintInfo();		//print: FChild

	//给b.info 重新赋值,调用 FBase::Set()
 	b.Set();			
	b.PrintInfo();		//print: FBase

	child.PrintInfo();  //print: FChild
baichi4141 2014-05-22
  • 打赏
  • 举报
回复
同不懂,求教

65,208

社区成员

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

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