首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >C++中的多态性和虚拟

C++中的多态性和虚拟
EN

Stack Overflow用户
提问于 2019-08-03 03:03:10
回答 3查看 153关注 0票数 0

我对C++中的多态性感到困惑。我自己在研究它,我理解它的主要特征。但是我不明白为什么它是有用的。在学习多态性(关于oop)之前,我学习了继承(这很有帮助,因为一个方法只能在超类和子类编写中使用一次)。现在我被多态和virtual关键字困扰了。我不明白为什么它是有用的。参见下面的代码(这是一个关于C++协会的练习(我将获得认证))。为什么我只能声明为“虚拟的”函数?我在代码中添加了变量n1n2n3 (作为公共变量),为什么我不能访问它们?我一点也不理解多态性,我在StackOverflow上读了很多关于多态性的帖子,但我好像理解了50%的多态性。我注意到在python中多态性不那么难理解,因为python没有数据类型,但我也想在C++中理解它,以及它可能的用途。

代码语言:javascript
复制
#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();
}
EN

回答 3

Stack Overflow用户

发布于 2019-08-03 03:22:31

也许一个例子可以帮助你。考虑不同的main(),如下所示:

代码语言:javascript
复制
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都是正确的做法。这类用例非常常见。

代码语言:javascript
复制
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关键字,它们都会说“嘘!嘘!”。

票数 5
EN

Stack Overflow用户

发布于 2019-08-03 03:47:53

你是对的,要理解多态性是如何有用的,以及它在学习它时做了什么并不容易。像您提到的常见示例并没有真正的帮助,它只是演示了概念,但缺乏真实的上下文。

理解和使用多态性是编程中比较高级的课题。它在遵循实体和设计模式等真正面向对象的编程时使用。

在现实世界中,迭代器设计模式是多义性的一个很好的例子。你用像next()这样的方法定义一个基类,比如list,然后你可以有不同的派生类(对于不同种类的list )都覆盖这个方法,他们实现它,所以你可以相应地迭代那个list。

正如你可能看到的,它变得很复杂,所以我不能在这里解释所有的东西,但是你可以得到一个想法和一些提示。

票数 0
EN

Stack Overflow用户

发布于 2019-08-03 23:32:42

多态性的关键思想是拥有一种方法。此方法将有不同的实现,并根据特定情况调用特定的实现。

让我们考虑这个例子:

代码语言:javascript
复制
#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();
}

当你运行这段代码时,你的输出如下:

代码语言:javascript
复制
From Polygon
From Polygon

让我们在基类(Polygon)中向set()添加virtual。下面是你得到的结果:

代码语言:javascript
复制
From Rectangle
From Triangle

如果我们在基类(Polygon)中创建了一个虚函数,并且它在派生类(在本例中是TriangleRectangle)中被覆盖,那么我们不需要在派生类中使用虚拟关键字,函数会自动被视为派生类中的虚函数。

这个想法是,如果set() 不是虚拟,那么set()将调用该方法的基类版本,即使set()指向Rect也是如此。另一方面,set() 是虚拟的,它将从派生类调用实际的方法。(在这种情况下,rect->set()将打印“从矩形”)。

这样做意味着,在我不知道对象的特定类型的情况下,我可以使用virtualpolymorphism,并且它将在调用期间使用正确的方法。

我希望这能帮到你!

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/57332139

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档