网站站点建设,网站开发计划和预算,彩票网站源码下载,什么网站可以申请做汉语老师在C中#xff0c;当我们把派生类对象向上强制转型为基类对象时#xff0c;会造成对象切割#xff08;Object slicing#xff09;问题。 请看下面示例代码#xff1a;
#include iostream
using namespace std;class CBase {
public:virtual ~CBase() default;v… 在C中当我们把派生类对象向上强制转型为基类对象时会造成对象切割Object slicing问题。 请看下面示例代码
#include iostream
using namespace std;class CBase {
public:virtual ~CBase() default;virtual void foo() {printf(print in Class CBase,this address:%p\n, this);}
};class CDerive : public CBase {
public:virtual void foo() override {printf(print in Class CDerive,this address:%p\n, this);}
};int main()
{CBase base;CDerive derive;CBase* pBase derive;cout \n本次调用的是pBase-CBase::foo()\n\t;pBase-CBase::foo();cout \n本次调用的是pBase-foo()\n\t;pBase-foo();cout \n本次调用的是 (static_castCBase(derive)).foo() \n\t;(static_castCBase(derive)).foo();
}代码运行结果如下 对于前两次调用成员函数foo的结果大家应该都清楚pBase是指向派生类对象的基类指针而foo成员函数是虚函数因此 pBase-foo() 调用的是派生类方法pBase-CBase::foo()由于指定了调用CBase的foo函数因此调用的是基类方法。另外foo函数打印出来的this指针的地址显示前两次调用的this指针是同一个也就是指向子类对象derive。 关键是最后一次调用的结果显示调用的是基类方法并且对象的地址也不是子类对象derive的地址。它的调用语句是 (static_castCBase(derive)).foo(); 这是为什么呢这涉及到对象切割(object slicing)。 在编译时编译器看到这句是要将派生类对象derive向上强制转为基类对象因此编译器以所谓的拷贝构造函数把derive中的CBase成分拷贝一份并把拷贝好的副本作为临时对象放在内存中。在运行期这个副本它是CBase对象调用foo函数时当然调用的是CBase::foo成员函数了 请注意如果我们把派生类对象的指针向上强制转为基类对象的指针那么转换后的基类指针仍然指向派生类对象。 总之当我们把派生类对象向上强制转型为基类对象时会经历对象切割Object slicing也就是编译器在内存中创建了一个子类对象的基类成分的副本这个临时对象与之前的子类对象无关。