1

假设我有一个基类和一个派生类。

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();

函数的签名不同,B会调用派生A还是基A?如果它会调用派生的B,我猜它会忽略参数?

如果派生的A需要不同的参数而不是没有参数,我是否必须将B的整个代码复制到派生类中才能改变B调用A的方式?

4

2 回答 2

2

函数的代码总是在定义它的类的上下文中计算。这包括确定每个表达式调用哪个函数。所以在里面Base::B(),这个调用A(x, y)被编译器翻译成对Base::A. 即使您稍后调用derived1.B(),它也会调用derived1 . Base::A(伪语法)。

唯一改变这一点的是虚函数。但是,即使使用它们,规则也是相似的。重载解析(基本上是将函数名称和签名与调用表达式匹配的过程)是在定义包含函数的类的上下文中完成的。如果该决议导致选择了一个虚函数,则将在运行时调用虚调用机制来调用该函数的适当覆盖。

让我们考虑这个例子:

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();

即使在这个例子中,调用d.bar()也会调用Derived::foo(int). 这是因为调用签名匹配是在 的上下文中完成的Base,它只看到并使用从到foo(int)的隐式转换doubleint.

于 2013-04-15T12:07:00.563 回答
0

两个原因迫使不Base::B打电话Base::ADerived::A

  • A它以特定的重载调用:A(int, int)
  • Base::A并且Base::B不是虚拟的,所以它调用Base::A. 代码不是多态的。

 

展示虚拟方法如何工作的最简单示例是:

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

但是,如果您使用不同AB参数写入(重载它),则必须使用实际参数显式调用它。

于 2013-04-15T12:01:32.640 回答