У нас есть следующий простой (и немного измененный, чтобы добавить main
и вывод) пример в стандарте:
struct A {
virtual void f()
{
cout << "A\n";
}
};
struct B : virtual A {
virtual void f()
{
cout << "B\n";
}
};
struct C : B, virtual A {
using A::f;
};
int main()
{
C c;
c.f(); // calls B::f, the final overrider
c.C::f();
return 0;
}
Из чего можно сделать вывод, что using A::f
не представляет переопределения. Но какая формулировка Стандарта диктует это? Вот формулировка окончательного переопределения из черновика C++17 ([class.virtual]p2):
‹...> Виртуальная функция-член C::vf объекта класса S является окончательным переопределением, если только самый производный класс (4.5), из которого S является подобъектом базового класса (если таковой имеется), объявляет или наследует другой член функция, которая переопределяет vf. В производном классе, если виртуальная функция-член подобъекта базового класса имеет более одного финального переопределения, программа имеет неправильный формат.
И я не смог найти, что на самом деле означает «переопределение». Если он не определен и мы рассматриваем любое объявление как переопределение, тогда мы должны рассматривать объявление using как переопределение, поскольку [namespace.udecl]p2 говорит:
Каждое использование-объявление является объявлением и объявлением-членом и поэтому может использоваться в определении класса.
Я понимаю намерение Стандарта использовать объявление, чтобы не вводить переопределение, но может ли кто-нибудь указать мне на фактические кавычки, которые говорят об этом на стандартном языке? Это первая часть, теперь вторая
Рассмотрим следующий код:
#include <iostream>
#include <string>
using std::cout;
class A {
public:
virtual void print() const {
cout << "from A" << std::endl;
}
};
class B: public A {
public:
void print() const override {
cout << "from B" << std::endl;
}
};
class C: public A {
public:
void print() const override {
cout << "from C" << std::endl;
}
};
class D: public B, public C {
public:
using C::print;
};
int main()
{
D d{};
d.print();
return 0;
}
Если объявление using не вводит переопределение, то у нас есть 2 окончательных переопределения в D
, следовательно, неопределенное поведение из-за
В производном классе, если виртуальная функция-член подобъекта базового класса имеет более одного финального переопределения, программа имеет неправильный формат.
Верно?