简体   繁体   English

我认为我将名称隐藏与功能覆盖混淆

[英]I think I'm confusing name hiding with function overriding

I'm confused...it seems that both things do the same thing. 我很困惑...似乎两件事都做同样的事情。

In this first code, I believe that the derived classes are hiding the function names of the base classes. 在第一个代码中,我相信派生类将隐藏基类的函数名称。

#include <iostream>

using namespace std;

class Quadrilateral {

public:
   void greeting() {
       std::cout << "i am a quadrilateral" << std::endl;
   }
};

class Square : public Quadrilateral {
 public:
    void greeting() {
        std::cout << "i am a square" << std::endl;
    }
};

class Trapezoid : public Quadrilateral {

public:
    void greeting() {   //hides greeting from quadrilateral function
        std::cout << "Hi I'm a Trapezoid" << std::endl;
    }
};

int main()
{
    Trapezoid tz;
    tz.greeting();  
}

This seems to have the same exact result: [here they are being overriden because it is virtual in the base class] 这似乎具有相同的确切结果:[此处被覆盖,因为它在基类中是虚拟的]

#include <iostream>
using namespace std;


class Quadrilateral {

public:

    virtual void greeting() {
        std::cout << "i am a quadrilateral" << std::endl;
    }
};

class Square : public Quadrilateral {
  public:
    void greeting() {
        std::cout << "i am a square" << std::endl;
    }
};

class Trapezoid : public Quadrilateral {

public:
    void greeting() {   //hides greeting from quadrilateral function
        std::cout << "Hi I'm a Trapezoid" << std::endl;
    }
};

int main()
{
    Trapezoid tz;
    tz.greeting();  
}

So I guess I'm just really confused as to...what is the difference? 所以我想我真的很困惑……有什么区别? Or what is the point of making it virtual in the base class if it's just gonna have the same effect in this situation? 或者,如果在这种情况下可以起到相同的作用,那么在基类中使其虚拟化又有什么意义呢?

Virtual functions are used to call the overriden function from the base class pointer. 虚函数用于从基类指针调用重写函数。 With your second example you can get the same result if you do the following in the main() 在第二个示例中,如果在main()执行以下操作,则可以获得相同的结果

 Trapezoid tz;
 Quadrilateral *base = &tz;
 base->greeting(); // it will print "Hi I'm a Trapezoid"

And this is the difference with the first example: possibility to call derived function from the base class pointer. 这与第一个示例有所不同:可以从基类指针调用派生函数。 If you not override the virtual base function in the derived class, then the base virtual function will be called. 如果未在派生类中覆盖虚拟基函数,则将调用基虚函数。

Usage example. 用法示例。

Imagine, that you want to create many objects with the base class Quadrilateral (for example five squares and three trapezoids): 想象一下,您想创建许多基类为Quadrilateral对象(例如,五个正方形和三个梯形):

Square sq1, sq2, sq3, sq4, sq5;
Trapezoid tz1, tz2, tz3;

Now, at some point in your code you want to go throw all of this objects and call the abstract function (in your case greeting() ). 现在,在代码中的某个时刻,您想抛出所有这些对象并调用抽象函数(在您的情况下, greeting() )。 So, with help of virtual function you can do it very simple: put all objects in an array of pointers and call the propper function. 因此,借助虚函数,您可以非常简单地完成操作:将所有对象放入指针数组中并调用propper函数。 Here is how: 方法如下:

Quadrilateral *base[8] = {&sq1, &sq2, &sq3, &sq4, &sq5, &tz1, &tz2, &tz3};
for (int i = 0; i < 8; i++) {
    base[i]->greeting();
}

In the output you will recieve five times "i am a square" and three times "Hi I'm a Trapezoid" . 在输出中,您将收到5次"i am a square"和3次"Hi I'm a Trapezoid" It comes vary helpfully when you create all different shapes (for example with different dimensions, properties) and want to go throw all of this objects and call, for example, calc() function to make an calculation individualy for each shape. 当您创建所有不同的形状(例如,具有不同的尺寸,属性)并想要抛出所有这些对象并调用(例如, calc()函数以对每个形状进行单独calc()时,它会有所不同。

I hope this helps you. 我希望这可以帮助你。

In C++, if you declare/have a struct or class variable like in this example, the compiler trivially knows its type and always calls the correct function, irrespective of virtual/not. 在C ++中,如果像本例中那样声明/拥有一个struct或class变量,则编译器将轻而易举地知道其类型,并且始终调用正确的函数,而与virtual / not无关。

Virtual functions only matter when dealing with pointers or references. 虚拟函数仅在处理指针或引用时才重要。

Try adding this after you existing code, before the end of main: 尝试在现有代码之后,main结束之前添加以下代码:

Quadrliateral *q = &t;
q->greeting();

And you will find it matters a lot whether all the greetings functions are virtual or not. 您会发现,所有问候功能是否都是虚拟的,都非常重要。

First of all, format your code please! 首先,请格式化您的代码!

First example 第一个例子

class Quadrilateral {
  public:
    void greeting() {
      std::cout << "i am a quadrilateral" << std::endl;
  }
};

class Square : public Quadrilateral {
  void greeting() {
    std::cout << "i am a square" << std::endl;
  }
};

class Trapezoid : public Quadrilateral {
  public:
    void greeting() {   //hides greeting from quadrilateral function
      std::cout << "Hi I'm a Trapezoid" << std::endl;
    }
};

int main() {
  Trapezoid tz;
  tz.greeting();  
}

In this example is totally normal that Trapezoid.greeting() hides Quadrilateral.greeting(): it's an overriding (same method name, same return, same parameters (none)). 在此示例中,Trapezoid.greeting()隐藏Quadrilateral.greeting()是完全正常的:这是一个覆盖(相同的方法名称,相同的返回值,相同的参数(无))。

Second example 第二个例子

class Quadrilateral {
  public:
   virtual void greeting() {
     std::cout << "i am a quadrilateral" << std::endl;
   }
};

class Square : public Quadrilateral {
  void greeting() {
    std::cout << "i am a square" << std::endl;
  }
};

class Trapezoid : public Quadrilateral {
 public:
  void greeting() {   //hides greeting from quadrilateral function
    std::cout << "Hi I'm a Trapezoid" << std::endl;
  } 
 };

int main() {
  Trapezoid tz;
  tz.greeting();  
}

The same. 相同。 You create an objcet of static-type Trapezoid that have dynamic-type Trapezoid. 您创建具有动态类型梯形的静态类型梯形的对象。 So tz.greeting will print "I'm a trapezoid" because greeting() is an override. 因此tz.greeting将显示“我是梯形”,因为greeting()是重写。

Third example 第三个例子

class Shape {
  public:
    virtual void greeting() {
      std::cout << "Shape" << std::endl;
  }
};

class Square : public Shape {
  /* override method greeting() of Shape class */
  void greeting() {
    std::cout << "Square" << std::endl;
  }
};

class Triangle : public Shape {
  public:
  /* override method greeting() of Shape class */
    void greeting() {   
      std::cout << "Triangle" << std::endl;
    }
};

int main() {
  Shape* shape = new Triangle();
  shape->greeting(); /* prints "Triangle" */
  shape = new Square();
  shape->greeting(); /* prints "Square" */
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何在 C++ 中模拟覆盖父函数(不隐藏)? - How can I simulate overriding a parent function (not hiding) in c++? 使用派生的 class 参数覆盖 function 是否被视为名称隐藏? - Is overriding a function with derived class argument considered name hiding? 如果我覆盖它,我可以调用基类的虚拟 function 吗? - Can I call a base class's virtual function if I'm overriding it? 我收到有关枚举的错误(我认为) - I'm getting an error concerning enum (I think) 我重写此方法的方式有什么问题? - What is wrong with the way I'm overriding this method? 我从以下代码中收到段错误。 我认为这与我的函数调用有关? - I'm getting a seg fault from the following code. I think it has something to do with my function call? g ++认为我没有传递引用 - g++ doesn't think I'm passing a reference 如果内部类具有与外部类同名的函数,它是否在C ++和Java中隐藏了重写或重载? - If an inner class has a function with the same name as an outer class, is it hiding overriding or overloading in C++ and Java? 我正在尝试SDL_DisplayFormat一个.png文件,我想,我可能会错过一个依赖项 - I'm trying to SDL_DisplayFormat a .png file, I think, I may be missing a dependency 在哈希映射中用 m.insert() 函数替换 am[nums[i]]=i 有什么问题,其中 m 是哈希映射的名称 - What is wrong in replacing a m[nums[i]]=i with a m.insert() function in hash map, where m is the name of the hash map
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM