使用基类指针调用虚函数
时间: 2023-09-17 22:12:01 浏览: 54
使用基类指针调用虚函数时,如果该指针所指向的对象是基类对象,那么将调用基类中的虚函数;如果该指针所指向的对象是派生类对象,那么将调用派生类中的虚函数,即使该虚函数在基类和派生类中的函数签名不同,也会被正确地调用。
例如,假设有一个基类Animal和一个派生类Cat,它们都有一个名为speak的虚函数。使用基类指针调用speak函数的示例代码如下:
```c++
Animal *ptr_animal = new Cat();
ptr_animal->speak(); // 调用Cat类中的speak函数
```
在这个示例中,ptr_animal指针指向Cat类的一个对象,但是通过基类指针调用speak函数时,会调用Cat类中的speak函数。这是因为Cat类重写了Animal类中的speak函数,并且这个函数被声明为虚函数,所以在运行时会调用正确的函数。
相关问题
那么派生类指针和基类指针调用虚函数有什么区别
在C++中,派生类可以继承基类的成员函数,包括虚函数。当基类指针或引用指向派生类对象时,如果该虚函数被声明为虚函数,则可以通过该指针或引用调用虚函数。这种情况下,基类指针或引用调用虚函数时,会根据指向的对象类型来确定调用哪个类的虚函数。
派生类指针和基类指针调用虚函数的区别在于,派生类指针调用虚函数时,会直接调用派生类中的虚函数,而基类指针调用虚函数时,会根据指向的对象类型来确定调用哪个类的虚函数。因此,如果派生类中重写了基类的虚函数,那么通过派生类指针调用虚函数时,会调用派生类中的虚函数;而通过基类指针调用虚函数时,会调用基类中的虚函数。
举个例子,假设有一个基类Animal和一个派生类Dog,它们都有一个虚函数speak()。如果我们用一个Animal指针指向一个Dog对象,那么通过Animal指针调用speak()时,会调用Animal类中的speak()函数;而通过Dog指针调用speak()时,会调用Dog类中的speak()函数。
1.设计一个基类动物类(animal),包含private数据成员:动物编号int num;和动物名称string name;public成员函数:getnum( )用于获取其编号, getname( )用于获取其名称和一个纯虚函数eat( ),以及构造函数。 2.由animal类派生出狗类dog和猫类cat,每个类中均有自己的构造函数,根据输出结果设计这两个类并在主函数中完成设计类的输出测试 3.要求在主函数中必须使用基类指针调用虚函数eat( ).
### 回答1:
1. 设计一个基类动物类(animal),包含private数据成员:动物编号int num;和动物名称string name;public成员函数:getnum()用于获取其编号,getname()用于获取其名称和一个纯虚函数eat(),以及构造函数。
2. 由animal类派生出狗类dog和猫类cat,每个类中均有自己的构造函数,根据输出结果设计这两个类并在主函数中完成设计类的输出测试。
3. 要求在主函数中必须使用基类指针调用虚函数eat()。
### 回答2:
1. 设计一个基类动物类(animal),包括以下内容:
```cpp
class Animal {
private:
int num;
std::string name;
public:
Animal(int num, std::string name);
int getnum() const;
std::string getname() const;
virtual void eat() = 0;
};
```
其中,构造函数需要初始化num和name成员,getnum和getname函数用于获取num和name的值,eat函数是纯虚函数,需要在派生类中实现。
2. 由animal类派生出狗类dog和猫类cat,每个类中均有自己的构造函数,根据输出结果设计这两个类并在主函数中完成设计类的输出测试。可参照以下代码:
```cpp
class Dog : public Animal {
public:
Dog(int num, std::string name) : Animal(num, name) {}
void eat() override {
std::cout << "Dog " << getname() << " is eating." << std::endl;
}
};
class Cat : public Animal {
public:
Cat(int num, std::string name) : Animal(num, name) {}
void eat() override {
std::cout << "Cat " << getname() << " is eating." << std::endl;
}
};
int main() {
Animal* a1 = new Dog(1, "Buddy");
Animal* a2 = new Cat(2, "Fluffy");
a1->eat(); // Output: Dog Buddy is eating.
a2->eat(); // Output: Cat Fluffy is eating.
delete a1;
delete a2;
return 0;
}
```
其中,Dog和Cat类均继承了Animal类的构造函数和getnum、getname函数,同时重写了eat函数,分别输出“Dog [name] is eating.”和“Cat [name] is eating.”的信息。在主函数中,分别用基类指针指向Dog和Cat对象,调用虚函数eat,可得到正确的输出结果。
3. 要求在主函数中必须使用基类指针调用虚函数eat。这在上面的代码中已经实现了,即通过Animal* a1和Animal* a2来调用虚函数eat。虚函数会根据对象的实际类型来选择调用具体的实现。在通过基类指针访问派生类对象时,如果该函数是虚函数,并且被覆盖,则调用派生类中对应的函数。这就是多态特性的体现,在代码上体现了“一个操作在不同的对象上有不同的实现”的特点。
### 回答3:
1. 首先设计一个基类动物类(animal),包含private数据成员:动物编号int num;和动物名称string name;public成员函数:getnum( )用于获取其编号,getname( )用于获取其名称和一个纯虚函数eat( ),以及构造函数。
class animal{
private:
int num; // 动物编号
string name; // 动物名称
public:
animal(int n, string na):num(n),name(na){} //构造函数
int getnum(){return num;} // 获取编号
string getname(){return name;} // 获取名称
virtual void eat() = 0; // 纯虚函数eat
};
2. 由animal类派生出狗类dog和猫类cat,每个类中均有自己的构造函数,根据输出结果设计这两个类并在主函数中完成设计类的输出测试。
class dog:public animal{
private:
string type; // 狗的类别
public:
dog(int n, string na, string t):animal(n,na),type(t){} //构造函数
void eat(){cout<<"狗狗正在吃骨头!"<<endl;} // eat函数的具体实现
};
class cat:public animal{
private:
string color; // 猫的颜色
public:
cat(int n, string na, string c):animal(n,na),color(c){} //构造函数
void eat(){cout<<"猫猫正在吃鱼腥!"<<endl;} // eat函数的具体实现
};
在主函数中进行输出的测试:
int main(){
animal *p1 = new dog(1,"小黑","金毛狮王");
animal *p2 = new cat(2,"咪咪","白色");
cout<<"编号为"<<p1->getnum()<<"的"<<p1->getname()<<"正在吃骨头:";
p1->eat();
cout<<"编号为"<<p2->getnum()<<"的"<<p2->getname()<<"正在吃鱼腥:";
p2->eat();
delete p1;
delete p2;
return 0;
}
输出结果为:
编号为1的小黑正在吃骨头:狗狗正在吃骨头!
编号为2的咪咪正在吃鱼腥:猫猫正在吃鱼腥!
3. 要求在主函数中必须使用基类指针调用虚函数eat()。
在上述主函数中,已经使用了基类指针调用了虚函数eat(),即
animal *p1 = new dog(1,"小黑","金毛狮王");
p1->eat();
animal *p2 = new cat(2,"咪咪","白色");
p2->eat();
因为在基类中声明了虚函数eat(),并且在派生类中分别实现了这个虚函数,即狗类中的eat()函数和猫类中的eat()函数,所以当基类指针指向派生类的对象时,调用虚函数eat()实际上会调用对应的派生类中的eat()函数。这样就实现了多态性。