Преобразование в базовый класс никогда не использовалось - PullRequest
0 голосов
/ 06 сентября 2018

У меня есть два класса, один из которых является производным от другого (потому что я не хочу раскрывать интерфейс базы). Однако позже я хочу создать ссылку на базу.

Я могу сделать это с помощью обычной функции-члена base(), но не с помощью оператора приведения, потому что этот оператор никогда не вызывается

Clang предупреждает об этом, потому что он говорит, что «он никогда не будет вызван».

Почему оператор приведения игнорируется и перезаписывается закрытым элементом? Это несоответствие в языке?

На самом деле, я думаю, что он имеет общедоступную базовую ссылку и ничего больше. Более того, если бы это сработало, это могло бы быть explicit.

class A{
    int v_;
public:
    void f(){}
};

class B : A{ // A is private base because I don't want the f() interface
    int w_;
public:
    A const& base() const{return *this;}
    /*explicit*/ operator A const&() const{return *this;} // never called, warning in clang
};

int main(){
    A a = {};
    B b = {};
    A const& a2 = b.base();
    A const& a3 = b; // bad, But why?
    A const& a4{b}; // explict doesn't help
    A const& a5 = b.operator A const&(); // works in clang (but with a contradictory warning), doesn't work with gcc
}

1 Ответ

0 голосов
/ 06 сентября 2018

В случаях a3 и a4 вы инициализируете ссылку с lvalue. В этой ситуации, если ссылочный тип является базовым классом типа инициализатора, ссылка привязывается непосредственно к инициализатору, в этом нет преобразований (C ++ 17 [dcl.init.ref] / 5).

Поскольку базовый класс недоступен, программа некорректна (dcl.init.ref / 4).

Я не уверен насчет правила проверки доступа в a5, хотя на практике это кажется спорным, поскольку вы не разработали бы код, чтобы кто-то должен был написать этот синтаксис.

См. Также [class.conv.fct] / 1:

Функция преобразования никогда не используется для преобразования (возможно, cv-квалифицированного) объекта в (возможно, cv-квалифицированный) тот же тип объекта (или ссылку на него) в (возможно, cv-квалифицированный) базовый класс этого тип (или ссылка на него), или (возможно, cv-квалифицированный) void.

...