C++:多态性:调用超级函数
C++: Polymorphism: Call Super Function
我有一个Animal
数组。
默认情况下,Animal
显示"Animal"
。
我也有Cat
,它延伸Animal
并说"Meow"
。
我也有Dog
,它延伸Animal
并说"Woof"
。
我想要什么:
Animal* a[2];
a[0] = new Cat();
a[1] = new Dog();
a[0]->talk(); //Meow
a[1]->talk(); //Woof
发生什么:
Animal* a[2];
a[0] = new Cat();
a[1] = new Dog();
a[0]->talk(); //Animal
a[1]->talk(); //Animal
//页眉
class Animal {
public:
Animal();
~Animal();
int talk() {return 0;}
};
class Cat : public Animal {
public:
Cat();
~Cat();
int talk() {return 1;}
};
class Dog : public Animal {
public:
Dog();
~Dog();
int talk() {return 2;}
};
//。.cpp
void letsHear(Animal *a) {
_LOG_INFO() << a->talk();
}
int main(){
Animal* a[2];
a[0] = (Animal *)new Cat();
a[1] = (Animal *)new Dog();
letsHear((Animal *)new Cat()); //0
letsHear((Animal *)new Dog()); //0
letsHear(new Animal()); //0
letsHear(a[0]); //0
letsHear(a[1]); //0
return 0;
}
Cat::Cat() {}
Cat::~Cat(){}
Dog::Dog() {}
Dog::~Dog() {}
Animal::Animal() {}
Animal::~Animal() {}
要在C++中获得多态行为,必须将函数声明为 virtual
。 在任何多态基类中使析构函数也成为虚拟是一个好主意:
class Animal {
public:
Animal();
virtual ~Animal();
virtual int talk() {return 0;}
};
您必须将
基方法talk()
声明为virtual
函数。看看这个例子。
class Animal {
public:
virtual void talk() {
cout << "Animal" << endl;
}
};
class Cat : public Animal {
public:
void talk() {
cout << "Meow" << endl;
}
};
class Dog : public Animal {
public:
void talk() {
cout << "Woof" << endl;
}
};
之后,您可以像示例中一样调用您的方法。
Animal *a[2];
a[0] = new Cat();
a[1] = new Dog();
a[0]->talk(); //Meow
a[1]->talk(); //Woof
你想要的称为动态调度,即根据要调用其成员函数的对象的类型选择要在运行时动态调用的函数。
在C++中,这是通过使用虚拟成员函数来实现的。若要使用它们,请将相应的成员函数声明为基类中的virtual
:
#include <iostream>
#include <array>
#include <memory>
using namespace std;
struct Animal {
virtual void speak() const {
cout << "Animal" << endl;
}
virtual ~Animal() {} // Better add this, too!
};
struct Cat : public Animal {
virtual void speak() const override {
cout << "Meow" << endl;
}
};
struct Dog : public Animal {
virtual void speak() const override {
cout << "Wuff" << endl;
}
};
int main() {
array<unique_ptr<Animal>, 3> animals;
animals[0] = make_unique<Cat>();
animals[1] = make_unique<Dog>();
animals[2] = make_unique<Animal>();
for (auto const & a : animals) {
a->speak();
}
return 0;
}
(现场示例(
如果(任何(派生类添加了成员字段,并且这些类的任何实例的所有权掌握在指向基类型的某个指针手中(如我的示例所示(,那么您应该遵循 aschelper 的建议并使基析构函数virtual
。否则,会出现内存泄漏。
您可以看到我在代码中使用了标准库中的一些概念,例如unique_ptr
和array
以及for
循环中的类型推断。应在适当的时候使用这些,在大多数情况下不再需要使用原始数组/指针,并且很容易导致内存管理错误。
相关文章:
- 函数调用中参数的顺序重要吗
- 基于另一个成员参数将函数调用从类传递给它的一个成员
- 变量没有改变?通过向量的函数调用
- 在两个类中共享相同的函数调用,并在不需要时避免空实例化
- 是否有C++编译器选项允许激进地删除所有函数调用,并将参数传递给具有空体的函数
- 我知道函数调用中存在歧义.有没有办法调用foo()函数
- 模板函数调用
- 获取从C++中同一类中的构造函数调用的方法返回的值
- 析构函数调用
- 成员函数调用和C++对象模型
- 使用共享指针的函数调用,其对象应为 const
- C++:编译时检查匹配的函数调用对?
- 函数调用C++中的参数太少
- 来自 DLL 的函数调用 [表观调用的括号前面的表达式必须具有(指向-)函数类型]
- 返回指向对象的指针的函数调用是否为 prvalue?
- C++ 如何重载 [] 运算符并进行函数调用
- 代码的效率. 转到和函数调用
- 是同一作用域的函数部分中的函数调用
- 如何封装一个函数,以便它只能由同一类中的一个其他函数调用?
- 类型擦除的std::function与虚拟函数调用的开销