简体   繁体   English

了解具有不同签名的继承和功能

[英]Understanding Inheritance and functions with different signatures

Say I have a base class and a derived class. 说我有一个基类和一个派生类。

class Base {
 public:
  void A(int x, int y) {do something}
  void B() {
    A(x,y);
    do something;
  }
};

class Derived : public Base {
  void A() {do something else};
};

Derived derived1;
derived1.B();

The signatures of the functions are different, will the B call the derived A or the base A? 函数的签名不同,B会调用派生的A还是基数A? Iif it will call the derived B, I guess it will dismiss the parameters? 如果它会调用派生的B,我猜想它将取消该参数吗?

what if the derived A needed different parameters rather than no parameters, would I have to copy B's entire code into the derived class just to change the way B calls A? 如果派生的A需要不同的参数而不是没有参数怎么办,我是否必须将B的整个代码复制到派生的类中,以改变B调用A的方式?

A function's code is always evaluated in the context of the class in which it is defined. 函数代码始终在其定义的类的上下文中进行评估。 This includes determining which function each expression calls. 这包括确定每个表达式调用哪个函数。 So inside Base::B() , the call A(x, y) is translated by the compiler as a call to Base::A . 因此在Base::B()内部,调用A(x, y)被编译器转换为对Base::A的调用。 Even if you later call derived1.B() , it will call derived1 . Base::A 即使您以后调用derived1.B() ,它也会调用derived1 . Base::A derived1 . Base::A (pseudo-syntax). derived1 . Base::A (伪语法)。

The only thing which changes this slightly is virtual functions. 仅有一点改变的是虚函数。 However, even with them, the rules are similar. 但是,即使有了它们,规则也是相似的。 Overload resolution (which is basically the process of matching a function name & signature to a call expression) is done in the context of the class where the containing function is defined. 重载解析(基本上是将函数名称和签名与调用表达式匹配的过程)是在定义包含函数的类的上下文中完成的。 If the resolution leads to a virtual function being selected, the virtual call mechanism will then be invoked at runtime to call the appropriate override of that function. 如果解决方案导致选择了虚拟函数,则将在运行时调用虚拟调用机制以调用该函数的适当替代

Let's consider this example: 让我们考虑这个例子:

struct Base {
  virtual void foo(int);
  virtual void bar() { foo(0.0); }
};

struct Derived : Base {
  virtual void foo(int);
  virtual void foo(double);
};

Derived d;
d.bar();

Even in this example, calling d.bar() will call Derived::foo(int) . 即使在此示例中,调用d.bar()也会调用Derived::foo(int) That's because the call-to-signature matching was done in the context of Base , which only sees foo(int) and employs the implicit conversion from double to int. 这是因为调用签名匹配是在Base上下文中完成的,后者仅看到foo(int)并采用从doubleint.的隐式转换int.

Two reasons force Base::B to call Base::A not Derived::A 迫使Base::B调用Base::A而不Derived::A两个原因

  • It's calling A with specific overload: A(int, int) 它以特定的重载调用AA(int, int)
  • Base::A and Base::B are not virtual, so it calls Base::A . Base::ABase::B不是虚拟的,因此它称为Base::A The code is not polymorphic. 该代码不是多态的。

The simplest example to show a how a virtual method works is: 显示虚拟方法如何工作的最简单示例是:

class Base {
public:
   virtual void A() {
      // do job #1
   }
};

class Derived : public Base {
public:
   virtual void A() {
      // do job #2
   }
};

// ...

Derived derived1;

Base *base = &derived1;

base->A(); // <---- It calls `Derived::A()` and does job #2

But, if you write A in B with different parameter (overload it), you have to call it explicitly with actual arguments. 但是,如果用不同的参数在BA (使它过载),则必须使用实际参数显式调用它。

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

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM