提防对象切片

来自《编写高质量代码:改善C++程序的150个建议》读书笔记

多态是C++的重要特征之一。多态的实现必须依靠指向同一类族的指针或引用,否则,可能出现对象切片的问题。

class Bird
{
public:
    Bird(const string& name) :m_name(name) {}
    virtual string Feature()const
    {
        return m_name + "can fly.";
    }
protected:
    string m_name;
};

class Parrot :public Bird
{
public:
    Parrot(const string& name, const string& food)
        :Bird(name), m_food(food) {}
    virtual string Feature() const
    {
        return (m_name + "can fly and likes to eat " + m_food);
    }
private:
    string m_food;
};

void DescribeBird(Bird bird)
{
    cout << bird.Feature() << endl;
}
int main()
{
    Bird bird1("Crow");
    DescribeBird(bird1);
    Parrot bird2("Polly", "millet");
    DescribeBird(bird2);
    return 0;
}
output:
Crow can fly.
Polly can fly.

当强制向上转换一个对象,而非对象的指针或引用时,会发生对象切片,保留下来的是一个子对象,而这个子对象对应于你的转换目标类型。

C++内存模型规定,如果出现继承结构,内存分布一定是先基类部分的数据,后派生类部分的数据。在派生类向基类映射的过程中,派生类对象中基类部分的数据会被强行“切”掉。“切”掉的基类部分没有被丢弃,而是将其当成了一个基类对象。
上述代码中,Parrot类对象bird2被切片后,会经由拷贝构造在栈上将其生成一个新的Bird对象,供函数DescribeBird使用。

采用对象指针或引用可以解决上述问题。

// 引用版
void DescribeBird(Bird& bird)
{
    cout << bird.Feature() << endl;
}
// 指针版
void DescribeBird(Bird* bird)
{
    cout << bird->Feature() << endl;
}

当类中没有虚拟机制时,也有可能发生对象切片,只不过这种情况下,编译器会提示出错信息。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值