С++ нет соответствующей функции для вызова метода базового класса из производного класса

Я немного запутался, так как gcc сбросил ошибку с сообщением

error: no matching function for call to ...
note: candidates are ...

Итак, я сделал неправильный вызов функции, как кажется. Вот что я действительно получил от gcc:

src/Services/UserService/UserService.cpp:17: error: no matching function for call to ‘Services::UserService::UserService::registerMethod(const char [6], Services::UserService::Request::LoginRequest* (Services::UserService::UserService::*)(std::map<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, Lib::request::Param, std::less<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<const std::basic_string<char, std::char_traits<char>, std::allocator<char> >, Lib::request::Param> > >&))’
src/Services/UserService/../../Lib/Service/Service.hpp:47: note: candidates are: void Lib::service::Service::registerMethod(std::string, Lib::request::Request* (Lib::service::Service::*)(std::map<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, Lib::request::Param, std::less<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<const std::basic_string<char, std::char_traits<char>, std::allocator<char> >, Lib::request::Param> > >&))

У меня есть базовый класс Lib::service::Service, производный от Services::UserService::UserService. И я сделал еще один базовый класс Lib::request::Request, производный от Services::UserService::Request::LoginRequest.

Базовый класс Lib::service::Service реализует метод под названием «registerMethod», который принимает строку и указатель на функцию.

typedef Lib::request::Request* (Lib::service::Service::*FuncPtr)(map<string, Param>&);

...

void registerMethod(string MethodName, FuncPtr Func);

Итак, небольшое форматирование вывода gcc дает мне следующее:

Запрошено:

Services::UserService::UserService::registerMethod(
    const char [6], 

    Services::UserService::Request::LoginRequest* (
        Services::UserService::UserService::*
    )(
        std::map<
            std::basic_string<char, std::char_traits<char>, std::allocator<char> >, 
            Lib::request::Param, 
            std::less<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, 
            std::allocator<std::pair<const std::basic_string<char, std::char_traits<char>, std::allocator<char> >, Lib::request::Param> > 
        >&
    )
)

И gcc говорит, что (и единственный - и тот, который я хочу использовать) кандидат:

void 
Lib::service::Service::registerMethod(
    std::string, 

    Lib::request::Request* (
        Lib::service::Service::*
    )(
        std::map<
            std::basic_string<char, std::char_traits<char>, std::allocator<char> >, 
            Lib::request::Param, 
            std::less<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, 
            std::allocator<std::pair<const std::basic_string<char, std::char_traits<char>, std::allocator<char> >, Lib::request::Param> > 
        >&
    )
)

Итак, поскольку Services::UserService::UserService является производным от Lib::service::Service и Serices::UserService::Request::LoginRequest является производным от Lib::request::Request, я думал, что это работает, как я определил для соответствия базовым классам и, следовательно, может использовать их и с производными классами.

Где я здесь не прав? Если это поможет, вот еще код ;-)

Спасибо!

С наилучшими пожеланиями,

Себастьян


namespace Lib {
    namespace service {
        class Service;
    }
}

namespace Lib {
    namespace request {

        class Request {
        public:
            Request(Lib::service::Service *Owner);
            virtual ~Request();

            virtual void Execute() = 0;

            void join(Lib::Session::Session *session);

        protected:
            Lib::service::Service *module;
            Lib::Session::Session *session;
            map<string, Param> params;

        private:
        };
    }
}

typedef Lib::request::Request* (Lib::service::Service::*FuncPtr)(map<string, Param>&);

namespace Lib {
    namespace service {

        class Service {
        public:
            const string Name;

            Service();
            virtual ~Service();

            Request* Call(string MethodName, map<string, Param> &Params);

        protected:
            void registerMethod(string MethodName, FuncPtr Func);

        private:
            map<string, FuncPtr> methods;
        };
    }
}

-

namespace Lib
{
    namespace service
    {

        Service::Service()
        {
        }

        Service::~Service()
        {
        }

        void Service::registerMethod(string MethodName, FuncPtr Func)
        {
            this->methods.insert(pair<string, FuncPtr>(MethodName, Func));
        }

        Request* Service::Call(string MethodName, map<string, Param> &Params)
        {
            FuncPtr Func;

            Func = this->methods[MethodName];
            Request *req = (*this.*Func)( Params );

            return req;
        }
    }
}

-

namespace Services {
    namespace UserService {

        class UserService : public Lib::service::Service {
        public:
            const string Name;

            UserService();
            virtual ~UserService();

            LoginRequest* Login(map<string, Param> &params);
            LogoutRequest* Logout(map<string, Param> &params);
        private:

        };
    }
}

-

namespace Services
{
    namespace UserService
    {

        UserService::UserService() : Name("UserModule")
        {
            this->registerMethod("Login", &UserService::Login);
            this->registerMethod("Logout", &UserService::Logout);
        }

        UserService::~UserService()
        {
        }

        LoginRequest* UserService::Login(map<string, Param> &params)
        {
            LoginRequest *request = new LoginRequest(this);

            //...

            return request;
        }

        LogoutRequest* UserService::Logout(map<string, Param> &params)
        {
            LogoutRequest *request = new LogoutRequest(this);

            //...

            return request;
        }

    }
}

person Sebastian Büttner    schedule 30.03.2013    source источник
comment
Это слишком много кода. Не могли бы вы создать небольшой самокомпилируемый пример, демонстрирующий вашу проблему? Скорее всего, вы сами найдете основную причину проблемы к тому времени, когда закончите с небольшим примером.   -  person Alok Save    schedule 30.03.2013
comment
Я не собираюсь пробираться через весь этот код. Сообщение об ошибке говорит вам, что не так. Часть, помеченная как несоответствующий вызов..., сообщает вам, что делает вызывающий код. Часть, помеченная кандидатами, ... сообщает вам, какие перегрузки она просматривала. Он не мог выбирать между ними.   -  person Pete Becker    schedule 30.03.2013
comment
@PeteBecker: Это проблема с так называемыми очками репутации SO. На плохие вопросы с отсутствием каких-либо усилий все равно будут даны ответы. Хотелось бы, чтобы на каждый вопрос был счетчик замораживания. На вопрос нельзя было ответить, если он не соответствовал некоторым основным критериям (усилие или ясность). спрашивающий модифицирует его достаточно, чтобы сделать основные критерии, на которые нельзя ответить, и размораживается для ответа, как только это будет сделано.   -  person Alok Save    schedule 30.03.2013
comment
Я не вижу, чтобы я прилагал к этому меньше усилий. Я уже писал там свои мысли, большинство из вас этого не читали, так как повторяли то, что я написал в первом посте. Я добавил важные части кода, как я видел во многих вопросах, что было опубликовано недостаточно кода, чтобы можно было четко ответить на проблему.   -  person Sebastian Büttner    schedule 31.03.2013


Ответы (2)


Кажется, вы забыли поставить void в объявлении тела метода. У вас есть код ниже, объявляющий метод в классе:

void registerMethod(string MethodName, FuncPtr Func);

Затем вы должны поставить void в объявлении тела.

void Services::UserService::UserService::registerMethod( ...
^^^^
person masoud    schedule 30.03.2013
comment
Метод никогда не перегружается. Он вызывает (и должен делать это!) метод базового класса, перед которым стоит пустота — void Service::registerMethod(string MethodName, FuncPtr Func) { ... } — я поместил определение этого класса в основной пост, чтобы уточнить это - person Sebastian Büttner; 30.03.2013

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

Однако, если кто-то еще столкнется с этим:

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

this->registerMethod("Login", reinterpret_cast<FuncPtr>(&UserService::Login));
person Sebastian Büttner    schedule 31.03.2013