当多态处理对象时,传地址与传值有明显的不同。
class Pet { string pname; public: Pet(const string& name): pname(name) { } virtual string name() const { return pname; } virtual string description() const { return "this is " + pname; } }; class Dog: public Pet { string favoriteActivity; public: Dog(const string& name, const string& activity) : Pet(name), favoriteActivity(activity) { } string description() const { return Pet::name() + " likes to " + favoriteActivity; } }; void describe(Pet p) { cout<<p.description()<<endl; } void newdescribe(Pet* p) { cout<<p->description()<<endl; } int _tmain(int argc, _TCHAR* argv[]) { Pet p("Alfred"); Dog d("Fluffy", "sleep"); describe(p); describe(d); newdescribe(&p); newdescribe(&d); system("pause"); return 0; } //this is Alfred //this is Fluffy //this is Alfred //Fluffy likes to sleep
结论:
第一,describe()接受的是一个Pet对象(而不是指针或引用),所以describe()中的任何调用都将引起一个与Pet大小相同的对象压栈并在调用后清除。这意味着,如果一个有Pet派生来的类的对象被传给describe(),则编译器会接受它,但只拷贝这个对象的对应于Pet的部分,切除这个对象的派生部分。
Dog对象d在切片过程中真的变成了一个Pet对象。
对象切片实际上是当它拷贝到一个新的对象时,去掉原来对象的一部分,而不是像使用指针或者引用那样简单地改变地址的内容。