在这种情况下,将派生类传递到具有基类引用arg的函数中,我会得到切片吗?

Do I get sliced for this case of passing derived classes into a function with base class reference arg?

本文关键字:函数 切片 arg 基类 派生 这种情况下 引用      更新时间:2023-10-16

我有以下程序

#include <iostream>
class Animal {
public:
    Animal(int age) : age_(age) {}
    virtual ~Animal() {}
    virtual void vocalize() = 0;
    virtual void description() = 0;
protected:
    int age_;
};
class Dog : public Animal {
public:
    Dog(int age, bool bites) : Animal(age), bites_(bites) {}
    virtual ~Dog() {}
    virtual void vocalize() {
        std::cout << "woff" << std::endl;
    }
    virtual void description() {
        std::cout << "Dog" << std::endl;
        std::cout << "age " << age_ << std::endl;
        std::cout << "bites " << bites_ << std::endl;
    }
private:
    bool bites_;
};
class Cat : public Animal {
public:
    Cat(int age, bool likes_tuna) : Animal(age), likes_tuna_(likes_tuna) {}
    virtual ~Cat() {}
    virtual void vocalize() {
        std::cout << "meow" << std::endl;
    }
    virtual void description() {
        std::cout << "Cat" << std::endl;
        std::cout << "age " << age_ << std::endl;
        std::cout << "likes tuna " << likes_tuna_ << std::endl;
    }
private:
    bool likes_tuna_;
};

int doStuff(Animal &animal) {
    animal.description();
    animal.vocalize();
}
int main() {
    Dog d(3, false);
    Cat c(5, true);
    doStuff(d);
    doStuff(c);
}

正如您所看到的,当我调用doStuff时,我将派生类传递给绑定到基类引用,然后调用一个纯虚方法,并由每个派生类重新实现。其中一个方法(description)同时使用基类(age_)和派生类(如es_tuna_和bites_)上的成员变量。我是被切了还是合法的?

我是被切了还是合法的?

你是不是得到切片。

多态性需要引用或指针,在本例中,您使用的是前者。这很好。你不是通过值传递参数给你的函数,而是通过引用,这就是允许对Animal的引用(doStuff()的参数)绑定到一个对象,其实际类型是Animal的子类。

当您尝试派生类的实例复制到派生类的实例中时,会发生

切片:

Animal a; // Pretend Animal is not abstract...
Dog d;
a = d; // Slicing!
Animal& a1 = d; // No slicing!
Animal* pA = &d; // No slicing!
pA = &a1; // No slicing!