0

我正在学习 c++。我在理解运行时多态性方面遇到问题?当通过创建类的对象可以完成相同的工作时,为什么我们需要使用引用/指针?

`例如:

class A{
private:
    int p;
public:
    A(){}   //ctor
    void Print(){}
    void display(){}
    void showrecord(){}
} 
class B:public A
{
Private:
     int q;
public:
    B(){}    //ctor
    void Print(){}  
    void displayrecord(){}
}

现在在上述情况下,我可以使用 B 类的对象和 A 类方法 b 使用范围解析来访问 B 类的任何方法,那么为什么要使用指针并将对象分配给它呢?

4

3 回答 3

1

假设你有 3 辆不同的汽车。你有不同的驱动它们的机制。驾驶员不需要了解底层发动机,而只需要了解如何驾驶汽车的协议,即踩下该踏板进行加速,踩下该踏板进行制动等。

现在从驾驶员的角度来看,无论是本田、福特还是别克。在他看来,这只是一辆汽车。同样,如果你有车棚,停放汽车的地方,你就称它们为车棚。它容纳汽车,并不关心每辆汽车是什么。所以

std::vector<Car*> v;
v.push_back(new Ferrari());
v.push_back(new Honda());
v.push_back(new Ford());

当通过创建类的对象可以完成相同的工作时,为什么我们需要使用引用/指针?

如果没有指针或引用,您就无法创建具有某些共性但在某些特定意义上不同的对象集合。这在一些严格的 OOP 语言(如 Java、C# 等)中通过使所有对象都派生自一个名为Object. C++ 是一种多范式语言,程序员可以自由地做出适合他/她的项目的决定。在 C++ 中执行此操作的一种方法是通过基类的指针。这个习语称为运行时多态性。

for (const auto &this_car : v)
     this_car->drive();

在这里,无论实际品牌如何,v只要基类car是类型的一部分,向量就可以容纳汽车。同样,drive每个品牌都会有所不同,但调用它的函数不需要知道这一点。

编辑:

感谢 nijansen 指出这篇文章实际上并没有回答这个问题:为什么运行时多态需要指针或引用(动态类型)?它只是说他们已经习惯于实现它,但没有解释为什么我们不能使用普通(静态类型)变量。

C++ 的设计方式是,一个对象的类型可能在编译时完全知道,也可能不知道,只需要手头的类型。我们Circle c;知道c是类型Circle;而在Shape *p = make_shape();我们真的不知道对象p指向什么;p自己的类型是Shape*,但其指向的对象的具体类型是未知的。我们所知道的是它指向某个派生自 的对象Shape。请不要将自己与动态或自动内存分配混淆;这对于自动变量也是一样的,例如Shape *p = &c;。在这里p,编译器也孤立地不知道对象的具体类型,它p指向的是什么。

如果我们写成p静态(非指针,非引用)类型Shape p = make_shape();,或者切片Shape p = c;中真正发生的事情将是具体类型,并且由于它不是指针,它会将对象的(形状)部分复制到它,这大多是不可取的。pShapeCirclec

在不知道底层类型的情况下,我们如何调用正确的具体类型的函数?C++ 提供了虚函数来完成这项工作。这就是为什么在 C++ 中总是用虚方法来解释运行时多态性的原因。而在 Java 和 C# 等语言中,所有方法都是虚拟的所有对象类型都是引用/指针。在某种程度上,您的问题的答案是,该语言被设计为需要引用/指针变量来实现运行时多态性

于 2013-10-07T10:46:36.693 回答
0

给你一个一般的例子,

请原谅伪代码。过段时间会加个Cpp代码,现在有点生疏了

超级班

Class Animal
{

}

子类

Class Dog : public Animal
{

}

Class Cat : public Animal
{

}

另一个班级,

class Vet 
{
    void checkAnimal(recieve Animal)
    {

    }          
}

现在考虑这种用法,

vetObject.checkAnimal(dogObject);
vetObject.checkAnimal(catObject);

如果不是因为多态性,您的 Vet Class 会是这样的,

class Vet 
{
    void checkAnimal(recieve Cat)
    {

    }          

    void checkAnimal(recieve Dog)
    {

    }          

     ....  and so on
}
于 2013-10-07T10:51:22.707 回答
0

因此,您可以对每个对象进行一些通用处理。例如,你有Chicken : Animal类,你有Cow : Animal类,它们有共同的功能doSlaughter(),你有SlaughterHouseJob类。当您要处理slaughterHouseJob.doSlaughterAnimals()方法时,您可以简单地编写以下代码:

for(Animal animal:animals){
    animal.doSlaughter(); //It can be chicken or Cow or other animals. Simply one function for all jobs
}
于 2013-10-07T10:53:05.010 回答