#cpp #qt #gcc #компилятор #стандарт
если в производном классе имеется функция с тем же именем, но различной сигнатурой? Пример. Создаем класс TwoStageMap, открыто унаследованного от QMap: template> class TwoStageMap : public QMap { public: void insert(const F &fkey, const S &skey, const T &value1); //TODO: return an iterator of what? void insert(const QPair &pair, const T &value1); T value(const F &fkey, const S &skey); T value(const QPair &pair); }; При попытки обратиться к value() с сигнатурой из производного класса (TwoStageMap) все прекрасно работает: TwoStageMap > tsMap; tsMap.insert(31, "October", "Halloween"); tsMap.insert(31, "December", "New Year's Eve"); tsMap.insert(25, "December", "Xmas"); tsMap.insert({25, "October"}, "Canna"); qDebug() << "Day1:" << tsMap.value1(31, "December"); , но как только попытаемся вызвать value() самого QMap (чтобы получить внутренний контейнер под первым ключем), tsMap.value(31);, то тут же получаем ошибку: no matching member function for call to 'value' При переименовании функции, например, в value1() проблема исчезает. Вопрос - это ошибка компилятора или стандарт языка? Компирятор gcc x86 64bit Реализация класса, если кто хочет его использовать/попробовать: template void TwoStageMap ::insert(const F &fkey, const S &skey, const T &value) { Cont innerMap; if (QMap ::contains(fkey)) { innerMap = QMap ::value(fkey); } innerMap.insert(skey, value); QMap ::insert(fkey, innerMap); //TODO: return an iterator of what? } template void TwoStageMap ::insert(const QPair &pair, const T &value) { return insert(pair.first, pair.second, value); } template T TwoStageMap ::value(const F &fkey, const S &skey) { auto innerMap = QMap ::value(fkey); return innerMap.value(skey); } template T TwoStageMap ::value(const QPair &pair) { return value1(pair.first, pair.second); } PS В примере Вызов функции_члена шаблонного базового класса из функции производного шаблонного класса ситуация с невидимостью неквалифицированного имени функции шаблонного родительского класса, с этим, как раз, вопросов нет, у меня, как можно видеть, идет обращение через QMap ::, здесь же немного другой случай, а именно, вопрос в том, что мешает компилятору распознать перегружанную функцию с другой сигнатурой, используя т.н. "искажение имен"? Если это стандарт языка, то вопрос, скорее к Комитету
Ответы
Ответ 1
При вызове метода класса по имени без квалификатора tsMap.value(31); для построения списка перегрузок будет осуществлен поиск имени без квалификатора в области видимости класса TwoStageMap согласно спецификации обращения к членам класса: 6.4.5 Class member access [basic.lookup.classref] 2 If the id-expression in a class member access (8.5.1.5) is an unqualified-id, and the type of the object expression is of a class type C , the unqualified-id is looked up in the scope of class C. Этот поиск будет завершен при нахождении имени value в классе TwoStageMap, так как поиск имени без квалификатора должен завершаться сразу при нахождении первого объявления, согласно спецификации поиска имени без квалификатора: 6.4.1 Unqualified name lookup [basic.lookup.unqual] 1 In all the cases listed in 6.4.1, the scopes are searched for a declaration in the order listed in each of the respective categories; name lookup ends as soon as a declaration is found for the name. Таким образом метод value из базового класса QMap в списке перегрузок будет отсутствовать. Чтобы это исправить можно Внести этот метод в область видимости класса TwoStageMap добавив using QMap::value; При вызове использовать имя с квалификатором: tsMap.QMap::value(31);Ответ 2
Если я правильно понял проблему, то решается эта проблема с помощью using. #include#include class Base { public: void func(int _v) { std::cout << __FUNCTION__ << std::endl; } }; class Derived : public Base { public: using Base::func; void func(const std::string &_str) { std::cout << __FUNCTION__ << std::endl; } }; int main(int argc, char *argv[]) { Derived d; d.func("text"); d.func(1); return 0; } Ответ 3
Не важно какой класс вы напишете. Допустим вы написали такой простой класс: class Your_class { protected: int n{ 3 }; public: int value(int n) const { return n + 3; } }; Если я наследую ваш класс, то я наследую все, что не является закрытым членами вашего класса: class My_class : public Your_class { }; В таком виде мой класс имеет функцию_член и обьект n вашего класса. Но как только я добавлю в класс: class My_class : public Your_class { public: bool value(const std::string& s) { return n == s.length(); } }; Этим я выражаю, что моя value это совсем другая функция(мне не нужен ваш вариант). И экземпляры моего класса не будут иметь возможность пользоваться одноименной функцией базового вашего класса. Для обеспечения этой возможности я смогу написать другую функцию, которая вызовит value вашего класса, или же сделать так, как описан в другом ответе. Точно также, если я добавляю в класс свой обьект n, то экземпляры моего класса будут пользоваться только этим обьектом. Так что, функция=член в производном классе с таким же именем, что и функция_ член в базовом, не является ее перегрузкой, а является ее заменой
Комментариев нет:
Отправить комментарий