Почему использование не может быть использовано для определения виртуальной функции?

Я недавно обнаружил использование using импортировать функцию базового класса в пространство имен производного класса (когда он скрыт). Я пытался использовать его для импорта функции из базового класса в качестве реализации функции в производном классе:

class A {
public:
  virtual void foo() = 0;
};

class B {
public:
  void foo() {
  }  
};

class C : public A, public B {
public:
  using B::foo;
};


int main()
{
  C c;
}

Это не скомпилируется как A::foo() это чисто виртуальная функция в C, Я надеялся что using B::foo; сделает реализацию foo(), Почему не так?

2 ответа

Решение

У вас есть две разные функции: A::foo() а также B::foo(), Хотя они имеют одинаковое безоговорочное имя, они не связаны между собой. B::foo() не может и не может переопределить A::foo() так как B не подкласс A,

C наследует обе функции от A а также B, Вы используете публичное наследование для обоих базовых классов, поэтому A::foo() а также B::foo() уже видны в C (обратите внимание, что вам нужно квалифицированное имя для вызова функций, чтобы избежать неоднозначности). Таким образом, ваше объявление об использовании фактически не имеет никакого эффекта.


Объявление использования, когда оно используется внутри класса, связано с перегрузкой, но не имеет ничего общего с переопределением. Это очень разные понятия.

Перегрузка - это использование разных функций с одинаковыми именами, но с разными наборами аргументов.

Переопределение - это полиморфизм, то есть наличие различных реализаций метода базового класса в производных классах.


Объявление using вводит имя функции из базового класса в производный класс, где это имя будет скрыто другой функцией с тем же именем, но с другими аргументами. Например:

class X
{  
 public:
  void func() {}
};

class Y : public X 
{  
 public:
  void func(int arg) {}
};

Y::func не переопределяет X::func, поскольку его аргументы разные. Кроме того, это также скрывает название func из базового класса, поэтому он может быть вызван только через определенное имя, например:

X x; 
x.func(); // ok

Y y; 
y.func(1); // ok, Y::func called 
y.func(); // error, base-class name func is hidden by local name 
y.X::func(); // ok, qualified name, X::func called 

В этом случае объявление using вводит имя из базового класса в производный класс, делая func вызываемый без уточнения имени:

class Y : public X 
{  
 public:
  using X::func; 
  void func(int arg) {}
};

// ...

Y y; 
y.func(); // ok, X::func called

using в C++ имеет другое значение и обозначает, что вы хотели бы иметь возможность доступа к функции / объекту в другом пространстве имен без явного ввода имени пространства имен. Это не имеет ничего общего с переопределением.

Другие вопросы по тегам