Мой друг показал мне следующий код
struct A {
virtual void f() = 0;
virtual void g() = 0;
};
struct AInternal : A {
virtual void f() { /* ... */ }
virtual void g() { /* ... */ }
};
Он использует AInternal
как внутренний класс, который реализует большинство (если не все A
). Затем он унаследовал от AInternal
, но как он этого хотел AInternal
остается недоступным (так как это деталь реализации), он наследует защищенный (реализованный в терминах). То, что он также сделал, было using
имя базового класса, чтобы сделать A
доступным (по умолчанию AInternal
был унаследован защищен тоже)
struct C : protected AInternal {
using AInternal::A;
};
На самом деле, это работало нормально (но, как мы выяснили позже, все равно сохранял функции-члены private
— только базовый класс был сделан public
), но это работало только на GCC. Не может сделать базу A
доступны. Любая идея? Мы могли бы даже сделать это, чтобы сломать код, который работает на Clang
struct C : public AInternal {
protected:
using AInternal::A;
};
C *c = 0;
A *a = c; // error on GCC!
Может кто-нибудь помочь, пожалуйста?
Вы влияете только на видимость имени введенного класса. Защита доступа базового подобъекта или его членов не должна быть затронута. Если Clang или GCC позволяют этому влиять на действительность броска или доступ в пределах базы, это их ошибка.
[class.member.lookup] 10.2 / 3 говоритВ наборе объявлений, using-декларации заменяются элементами, которые они обозначают, а объявления типов (в том числе injected-class-names) заменяются типами, которые они обозначают.
Подобъект базового класса не имеет имени при поиске члена; имя введенного класса делает.
Других решений пока нет …