我对C++中的多态性感到困惑。我自己在研究它,我理解它的主要特征。但是我不明白为什么它是有用的。在学习多态性(关于oop)之前,我学习了继承(这很有帮助,因为一个方法只能在超类和子类编写中使用一次)。现在我被多态和virtual关键字困扰了。我不明白为什么它是有用的。参见下面的代码(这是一个关于C++协会的练习(我将获得认证))。为什么我只能声明为“虚拟的”函数?我在代码中添加了变量n1、n2、n3 (作为公共变量),为什么我不能访问它们?我一点也不理解多态性,我在StackOverflow上读了很多关于多态性的帖子,但我好像理解了50%的多态性。我注意到在python中多态性不那么难理解,因为python没有数据类型,但我也想在C++中理解它,以及它可能的用途。
#include <iostream>
using namespace std;
class Pet {
protected:
string Name;
public:
Pet(string n) { Name = n; }
virtual void MakeSound(void) { cout << Name << " the Pet says: Shh! Shh!" << endl; }
int n1;
};
class Cat : public Pet {
public:
Cat(string n) : Pet(n) { }
void MakeSound(void) { cout << Name << " the Cat says: Meow! Meow!" << endl; }
int n2;
};
class Dog : public Pet {
public:
Dog(string n) : Pet(n) { }
void MakeSound(void) { cout << Name << " the Dog says: Woof! Woof!" << endl; }
int n3;
};
int main(void) {
Pet* a_pet1, * a_pet2;
Cat* a_cat;
Dog* a_dog;
a_pet1 = a_cat = new Cat("Kitty");
a_pet2 = a_dog = new Dog("Doggie");
a_pet1->MakeSound();
a_cat->MakeSound();
static_cast<Pet*>(a_cat)->MakeSound();
a_pet2->MakeSound();
a_dog->MakeSound();
static_cast<Pet*>(a_dog)->MakeSound();
}发布于 2019-08-03 03:22:31
也许一个例子可以帮助你。考虑不同的main(),如下所示:
int main()
{
std::vector<std::unique_ptr<Pet>> menagerie;
menagerie.push_back(std::make_unique<Dog>("Fido"));
menagerie.push_back(std::make_unique<Cat>("Morris"));
menagerie.push_back(std::make_unique<Cat>("Garfield"));
menagerie.push_back(std::make_unique<Dog>("Rover"));
for (auto&& pet : menagerie)
{
pet->MakeSound();
}
}这里有一群宠物。我们可以用相同的方式处理它们,但是它们发出不同的声音。对每种宠物调用MakeSound都是正确的做法。这类用例非常常见。
Fido the Dog says: Woof! Woof!
Morris the Cat says: Meow! Meow!
Garfield the Cat says: Meow! Meow!
Rover the Dog says: Woof! Woof!现在,尝试删除virtual关键字,它们都会说“嘘!嘘!”。
发布于 2019-08-03 03:47:53
你是对的,要理解多态性是如何有用的,以及它在学习它时做了什么并不容易。像您提到的常见示例并没有真正的帮助,它只是演示了概念,但缺乏真实的上下文。
理解和使用多态性是编程中比较高级的课题。它在遵循实体和设计模式等真正面向对象的编程时使用。
在现实世界中,迭代器设计模式是多义性的一个很好的例子。你用像next()这样的方法定义一个基类,比如list,然后你可以有不同的派生类(对于不同种类的list )都覆盖这个方法,他们实现它,所以你可以相应地迭代那个list。
正如你可能看到的,它变得很复杂,所以我不能在这里解释所有的东西,但是你可以得到一个想法和一些提示。
发布于 2019-08-03 23:32:42
多态性的关键思想是拥有一种方法。此方法将有不同的实现,并根据特定情况调用特定的实现。
让我们考虑这个例子:
#include <iostream>
using namespace std;
class Polygon{
protected:
int numVertices;
float *xCoord, *yCoord;
public:
void set(){
cout<<"From Polygon"<< endl;
}
};
class Rectangle : public Polygon{
public:
void set(){
cout<<"From Rectangle"<< endl;
}
class Triangle : public Polygon{
public:
void set(){
cout<<"From Triangle"<< endl;
}
};
int main(){
Polygon *poly;
Rectangle rec;
Triangle tri;
poly = &rec;
poly->set();
poly = &tri;
poly->set();
}当你运行这段代码时,你的输出如下:
From Polygon
From Polygon让我们在基类(Polygon)中向set()添加virtual。下面是你得到的结果:
From Rectangle
From Triangle如果我们在基类(Polygon)中创建了一个虚函数,并且它在派生类(在本例中是Triangle和Rectangle)中被覆盖,那么我们不需要在派生类中使用虚拟关键字,函数会自动被视为派生类中的虚函数。
这个想法是,如果set() 不是虚拟,那么set()将调用该方法的基类版本,即使set()指向Rect也是如此。另一方面,set() 是虚拟的,它将从派生类调用实际的方法。(在这种情况下,rect->set()将打印“从矩形”)。
这样做意味着,在我不知道对象的特定类型的情况下,我可以使用virtual和polymorphism,并且它将在调用期间使用正确的方法。
我希望这能帮到你!
https://stackoverflow.com/questions/57332139
复制相似问题