2015-08-14 4 views
0

У меня есть некоторый абстрактный класс, и мне интересно, смогу ли я объявить функцию с этой подписью внутри него:Можно ли объявить чистую виртуальную функцию с выведенным типом возврата? Если нет, почему бы и нет?

virtual auto some_function() = 0; 

В случае помогает отвечая, я пытаюсь реализовать класс, который позволит регистрировать обратные вызовы для разных типов, так что, когда вызывается функция шаблона члена, он будет искать свой аргумент typeid в ассоциативном контейнере и вызывать его связанный с ним обратный вызов.

ОБОСНОВАНИЕ Оригинальность ВОПРОС

Согласно N3638 - Return type deduction for normal functions

можно было бы разрешить возвращение типа вычет виртуальных функций (...)

так в то время как автоматический виртуальный не разрешен в C++, это возможный альтернативный дизайн в соответствии с Jason Merrill.

Так что этот вопрос: Можно ли объявить чистую виртуальную функцию с выведенным типом возврата? Если нет, почему бы и нет? (Я исправил заголовок, чтобы соответствовать реальному вопросу и его намерению) не совпадает с ответом на вопрос Можно ли объявить виртуальную функцию с выведенным типом возврата?

Возможно, это помогло бы, если бы модераторы рассмотрели вопрос, а не только его название.

+0

Хорошо, я знал, что, скорее всего, это будет невозможно. Теперь, когда я точно знаю, любая помощь с другой частью моего поста? – Dani

+1

Я не понимаю, кейс. Какой код вы хотите использовать? Ответ - это, вероятно, магия шаблона. –

+0

@ Дани Скажите нам, что вы пытаетесь сделать (НЕ, как вы этого хотите), даже некорректный псевдокод может помочь. – curiousguy

ответ

0

Вопрос не имеет смысла.auto средство выводится из инициализации:

auto i = 1; // int 

или выводится из return заявления:

auto f() { return 2; } // int 

Чисто виртуальная функция по определению не имеет определение виртуальной функции (*), так что не имеет инструкции return, , поэтому тип возврата не может быть выведен из чего-либо.

У вас должно быть неправильное понимание C++, чтобы думать, что это может сработать.

Краткий ответ: C++ статически типизирован.

дополнительные детали

Примечание (*): Чисто виртуальная функция может иметь определение, но это определение не-виртуальной функции вызываемой с областью разрешения оператора:

struct Base { 
    virtual void f() = 0; 
}; 

void Base::f() { 
    std::cout << "Base::f()\n"; 
} 

struct Der : Base { 
    virtual void f(); 
}; 

void Der::f() { 
    cout << "Der::f()\n"; 
} 

int main() { 
    Der d; 
    d.Base::f(); 
} 

Тест here; выходы:

Base::f() 

OTOH, Base::f() нельзя назвать через механизм виртуального вызова:

struct Base { 
    Base(); 
    virtual void f() = 0; 
}; 

void call (Base *p) { 
    cout << "Base::Base()\n"; 
    p->f(); 
} 

Base::Base() { 
    call(this); 
} 

Test here; генерирует:

Runtime error 

Чистая виртуальная функция не может быть названо практически.

Тип возвращаемой чистой формы функции может быть выведен из оператора возврата из не виртуального определения (**), но он создаст еще один частный случай и не решит данную проблему (оператор return не известно в базовом классе).

(**) Виртуальная функция не может быть объявлена ​​auto на C++, но нет веских причин для отказа от виртуальной функции auto.

Ответить на комментарий

Возвращение типа можно гипотетически вывести из производного класса реализации.

Хорошо, допустим, что мы:

struct Base { 
    virtual auto f() = 0; 
}; 

struct Der1 : Base { 
    virtual int f(); 
}; 

Тогда возвращаемый тип Base::f() является ИНТ, верно? Это предполагает, что Der можно найти в компиляторе, даже если оно определено последним, в другом месте, а программа скомпилирована отдельно (или, может быть, вы предположите, что эта функция не совместима с отдельной компиляцией?). Теперь класс может быть получен в другом месте:

struct Der2 : Base { 
    virtual std::string f(); 
}; 

Так что тип возвращаемого типа Base::f()? int, string, no, both, a cat?

В C++ выражение должно иметь тип хорошо определенный: тип объявлен, он же время компиляции типа, он же статического типа. Эти слова эквивалентны.

Например, указатель типа переменной DECLARE никогда не меняется, не делает заявленный тип *p, но реальная ака среда ака динамический тип *p зависит от величины p:

Base *p = 0; 

// declared type of p is Base*, real type of *p is Base, 
// declared type of *p is Base, real type of *p is undefined 
cout << "typeid (p): " << typeid (p).name() << "\n"; 

p = new Der1; 
// declared type of p is Base*, real type of *p is Base, 
// declared type of *p is Base, real type of *p is Der1 
cout << "typeid (p): " << typeid (p).name() << "\n"; 
cout << "typeid (*p): " << typeid (*p).name() << "\n"; 

Заявленная типа используется компилятором:

  • для поиска имени
  • для разрешения перегрузки (перегруженных функций, не являющихся членов, перегруженной членом Func ЦИИ, перегруженные операторы)
  • для доступа к члену проверки (public, protected, private)

Реальный тип управляет поведением виртуального вызова во время выполнения.

Различие объявленного против реального типа является одной из важнейших концепций C++!

+1

Тип возврата можно было бы вывести из реализации производного класса с помощью hipothetically. Тот факт, что чистая виртуальная функция не имеет оператора return, не должна быть проблемой, поскольку абстрактные классы не могут быть созданы. Так я и думал, что это может сработать на случай. Похоже, что это создаст гораздо больше проблем, чем это решит. – Dani

+1

Какой производный класс? Регулярная функция, которая используется в программе, должна иметь ровно одно определение. ** Класс может иметь нулевые или более производные классы. ** Как компилятор найдет производный класс? В каком TU (единица перевода)? Вы хотите, чтобы производный класс определялся сразу после базового класса? – curiousguy

+1

В таком случае была бы другая функция с другой сигнатурой для каждого из производных классов. Очевидно, что это была бы не одна и та же функция, так как каждая из них была охвачена классом. В течение трех последних вопросов я не являюсь экспертом в деталях реализации компилятора или языка. Во всяком случае, на данный момент я понял, что это не очень разумная вещь, и что она не соответствует статически типизированной природе C++. Спасибо, что указали мне, почему. – Dani