#include<iostream> using namespace std; class Animal1 { public: //Speak函数就是虚函数 //函数前面加上virtual关键字,变成虚函数,那么编译器在编译的时候就不能确定函数调用了。 void speak() { cout << "动物在说话" << endl; } }; class Cat1 :public Animal1 { public: virtual void speak() { cout << "小猫在说话" << endl; } }; class Dog1 :public Animal1 { public: virtual void speak() { cout << "小狗在说话" << endl; } }; class Animal2 { public: //Speak函数就是虚函数 //函数前面加上virtual关键字,变成虚函数,那么编译器在编译的时候就不能确定函数调用了。 void speak() { cout << "动物在说话" << endl; } }; class Cat2 :public Animal2 { public: void speak() { cout << "小猫在说话" << endl; } }; class Dog2 :public Animal2 { public: void speak() { cout << "小狗在说话" << endl; } }; int main(){ Cat2 cat_; Dog2 dog_; ;//定义Animal类指针a,指向cat_ Animal2 *b=&dog_; //a b为Animal类指针,且调用函数不为虚函数,编译器只会调用父类成员函数 ;//通过指针a调用speak() b->speak(); Cat1 cat; Dog1 dog; Animal1 *c=&cat; Animal1 *d=&dog; //虽然都是Animal类指针,但因为现在是虚函数,编译器会考察指针实际指向 c->speak(); d->speak(); return 0; //输出为: // // // // }
时间: 2024-04-26 15:24:27 浏览: 94
这段代码主要演示了虚函数的使用,以及基类指针指向派生类对象时虚函数的表现。
其中Animal1、Cat1和Dog1三个类都声明了虚函数speak(),Animal2、Cat2和Dog2三个类没有声明虚函数speak()。
在main函数中,先定义了一个Cat2对象和一个Dog2对象,并分别定义一个Animal2类指针b,指向Dog2对象。然后通过b调用speak()函数,发现输出的是"动物在说话",而不是"小狗在说话",因为Animal2、Cat2和Dog2类中的speak()函数都不是虚函数。
接下来定义了Cat1对象和Dog1对象,并定义两个Animal1类指针c和d,分别指向Cat1对象和Dog1对象。通过c和d调用speak()函数,输出的是"小猫在说话"和"小狗在说话",因为Animal1、Cat1和Dog1类中的speak()函数都是虚函数,且指针c和d实际指向的对象是Cat1和Dog1,因此调用的是它们各自的speak()函数。
需要注意的是,虚函数的作用只有在通过基类指针或引用调用虚函数时才会发挥出来,如果直接通过对象调用虚函数,编译器会直接调用对象类中的函数,而不是基类中的虚函数。
相关问题
#include <iostream> #include <vector> using namespace std; class Animal{ public: virtual void speak(){ cout<<"动物叫"<<endl; }; }; class Dog:public Animal{ public: virtual void speak(){ cout<<"小狗汪汪叫"<<endl; } }; class Cat:public Animal{ public: virtual void speak(){ cout<<"小猫喵喵叫"<<endl; } }; class Pig:public Animal{ public: virtual void speak(){ cout<<"小猪嗡嗡叫"<<endl; } }; int main() { vector<Animal> animals; Cat cat; Dog dog; Pig pig; animals.push_back(cat); animals.push_back(dog); animals.push_back(pig); for (vector<Animal>::iterator it= animals.begin(); it!=animals.end() ; it++) { it->speak(); } return 0; }
这段代码有一个问题,即无法正确输出子类的特定方法。原因是当把子类对象存储在vector<Animal>中时,实际上会发生对象切割(object slicing)现象,即只会保留父类Animal的部分,而子类的特定方法会被删除,导致无法正确输出。
要解决这个问题,可以将vector中的元素类型修改为指向Animal的指针,如下所示:
```
int main() {
vector<Animal*> animals;
Cat cat;
Dog dog;
Pig pig;
animals.push_back(&cat);
animals.push_back(&dog);
animals.push_back(&pig);
for (vector<Animal*>::iterator it = animals.begin(); it != animals.end(); it++) {
(*it)->speak();
}
return 0;
}
```
这样就可以正确输出子类的特定方法了。注意,在存储子类对象时需要使用取地址符&,而在访问时需要使用解引用符*,这是因为存储的是指针类型的指针。
另外,由于Animal类中的speak方法被声明为虚函数,因此在运行时会根据实际类型来调用子类的特定方法。这就是多态性的体现。
#include <iostream> #include <vector> #include <algorithm> using namespace std; class Animal; public: string name_animal; int age_animal; virtual void speak(){ cout<<"I am an animal."<<endl;} }; class Cat:public Animal{ public: void speak(){ cout<<"I am a cat."<<endl; class Dog:public Animal{ public: void speak(){cout<<"I am a dog."endl;} Animal(string name, int age):name_animal(name),age_animal(age){}; bool cmp2(Animal t1, Animal t2){ return t1.age_animal > t2.age_animal; } int main(){ vector <Animal> animalList; Animal t1={"LittleDog",8}; animalList.push_back(t1); Animal t2={"LittleCat",3}; animalList.push_back(t2); Animal t3={"LittleLion",5}; animalList.push_back(t3); sort(animalList.begin(),animalList.end(),cmp2); for (int j=0; j<animalList.size(); j++){ cout<<"Name:"<<animalList[j].name_animal<<"Age:"<<animalList[j].age_animal<<endl; } Animal *animal1=new Cat(); Animal &animal2=*new Dog; animal->speak(); animal2.speak(); delete animal; delete &animal2; return 0; } 帮我看看这段C++代码中有什么错误吗?尤其是vector <Animal>那一段的错误
这段代码存在以下错误:
1. 在 Animal 类定义的时候,缺少了类的左括号。
2. 在 Cat 类定义的时候,缺少了类的右括号。
3. 在 Dog 类定义的 speak 函数的实现中,缺少了输出语句的结束符号 “;”。
4. 在 vector <Animal> animalList 定义的时候,Animal 类没有默认构造函数,因此需要在定义 vector 时提供初始值,例如 vector <Animal> animalList = {t1, t2, t3};。
5. 在 bool cmp2 函数的定义中,应该将其定义为静态成员函数或者全局函数,因为它需要在 sort 函数中作为比较函数使用。
6. 在 main 函数中,Animal *animal1=new Cat(); 这句代码定义了一个 Animal 类型的指针 animal1,但是它指向了一个 Cat 类型的对象,应该将 Animal 类定义为一个抽象类,然后再派生出 Cat 和 Dog 类。此外,这里没有使用 animal1 指针,可以将其删除。
7. 在 Animal &animal2=*new Dog; 这句代码中,new 操作符返回的是指向对象的指针,应该将其声明为 Dog* 类型的指针,然后取其引用。此外,在这里没有使用 animal2 引用,可以将其删除。
下面是改正后的代码:
```
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
class Animal {
public:
string name_animal;
int age_animal;
virtual void speak() = 0;
};
class Cat : public Animal {
public:
void speak() {
cout << "I am a cat." << endl;
}
};
class Dog : public Animal {
public:
void speak() {
cout << "I am a dog." << endl;
}
};
bool cmp2(Animal t1, Animal t2) {
return t1.age_animal > t2.age_animal;
}
int main() {
vector<Animal> animalList = {{"LittleDog", 8}, {"LittleCat", 3}, {"LittleLion", 5}};
sort(animalList.begin(), animalList.end(), cmp2);
for (int j = 0; j < animalList.size(); j++) {
cout << "Name:" << animalList[j].name_animal << " Age:" << animalList[j].age_animal << endl;
}
Animal *animal = new Cat();
Animal *animal1 = new Dog();
animal->speak();
animal1->speak();
delete animal;
delete animal1;
return 0;
}
```
阅读全文