Я пытаюсь обобщить свой класс, используя дизайн на основе политик, и кажется, что gcc не видит реализацию чисто виртуальных функций, которые реализованы в базовых классах. Вот пример:
#include <iostream>
template <typename ReturnValue, template <typename> class... AccessPolicies>
struct testInterface : public AccessPolicies< ReturnValue >::interface...
{
};
template <typename DataClass, typename ReturnValue, template <typename> class... AccessPolicies>
struct testImplementation : public DataClass,
public testInterface< ReturnValue, AccessPolicies... >,
public AccessPolicies< ReturnValue >::template implementation< DataClass >...
{
};
template < typename ReturnValue >
struct GetByIndex;
template <>
struct GetByIndex< std::string >
{
class interface
{
public:
virtual std::string operator[](size_t ) = 0;
protected:
virtual ~interface() = default;
};
template <class DataClass>
class implementation
{
public:
virtual std::string operator[](size_t )
{
return "test by index";
}
protected:
virtual ~implementation() = default;
};
};
template < typename ReturnValue >
struct GetByName;
template <>
struct GetByName< std::string >
{
class interface
{
public:
virtual std::string operator[](std::string ) = 0;
protected:
virtual ~interface() = default;
};
template <class DataClass>
class implementation
{
public:
virtual std::string operator[](std::string )
{
return "test by string";
}
protected:
virtual ~implementation() = default;
};
};
struct data
{
};
int main()
{
testImplementation< data, std::string, GetByIndex, GetByName> test;
testInterface< std::string, GetByIndex, GetByName >& Test = test;
std::cout << Test[5] << std::endl;
return 0;
}
Я получаю следующие ошибки:
..\nienazwany\main.cpp: In function 'int main()':
..\nienazwany\main.cpp:78:67: error: cannot declare variable 'test' to be of abstract type 'testImplementation<data, std::basic_string<char>, GetByIndex, GetByName>'
testImplementation< data, std::string, GetByIndex, GetByName> test;
^
..\nienazwany\main.cpp:10:8: note: because the following virtual functions are pure within 'testImplementation<data, std::basic_string<char>, GetByIndex, GetByName>':
struct testImplementation : public DataClass,
^
..\nienazwany\main.cpp:53:29: note: virtual std::string GetByName<std::basic_string<char> >::interface::operator[](std::string)
virtual std::string operator[](std::string ) = 0;
^
..\nienazwany\main.cpp:26:29: note: virtual std::string GetByIndex<std::basic_string<char> >::interface::operator[](size_t)
virtual std::string operator[](size_t ) = 0;
^
..\nienazwany\main.cpp:81:24: error: request for member 'operator[]' is ambiguous
std::cout << Test[5] << std::endl;
^
..\nienazwany\main.cpp:53:29: note: candidates are: virtual std::string GetByName<std::basic_string<char> >::interface::operator[](std::string)
virtual std::string operator[](std::string ) = 0;
^
..\nienazwany\main.cpp:26:29: note: virtual std::string GetByIndex<std::basic_string<char> >::interface::operator[](size_t)
virtual std::string operator[](size_t ) = 0;
Есть две проблемы, которые я не совсем понимаю:
AccessPolicy< ReturnType >::implementation< DataClass >...
быть реализацией AccessPolicy< ReturnType >::interface...
хотя сигнатуры функций абсолютно одинаковы.Есть идеи, почему это происходит?
Я предполагаю, что, хотя я наследую напрямую от «интерфейса» и «реализации», функции-члены каким-то образом оказываются в разных пространствах имен. Если это правильно, как мне обойти это?
РЕДАКТИРОВАТЬ : добавил приведенный выше пример без шаблонов, согласно запросу
#include <iostream>
class GetByIndexInterface
{
public:
virtual std::string operator[](size_t ) = 0;
protected:
virtual ~GetByIndexInterface() = default;
};
class GetByIndexImplementation
{
public:
virtual std::string operator[](size_t )
{
return "test by index";
}
protected:
virtual ~GetByIndexImplementation() = default;
};class GetByNameInterface
{
public:
virtual std::string operator[](std::string ) = 0;
protected:
virtual ~GetByNameInterface() = default;
};
class GetByNameImplementation
{
public:
virtual std::string operator[](std::string )
{
return "test by string";
}
protected:
virtual ~GetByNameImplementation() = default;
};
struct data
{
};
struct testInterface : public GetByIndexInterface,
public GetByNameInterface
{
};
struct testImplementation : public data,
public testInterface,
public GetByIndexImplementation,
public GetByNameImplementation
{
};
int main()
{
testImplementation test;
testInterface& Test = test;
std::cout << Test[5] << std::endl;
return 0;
}
Вы struct testImplementation
наследуется от struct testInterface
сам по себе наследует от struct GetByNameInterface
который определяет virtual std::string operator[](std::string ) = 0;
ни testInterface
ни testImplementation
определяем переопределение для этого виртуального, так testImplementation
это абстрактная структура.
Тот факт, что вы наследуете от другого класса, который не имеет отношения к предыдущему, но определяет тот же operator
не поможет тебе. Вы должны реализовать свой метод в иерархии между вашей конкретной реализацией и вашим абстрактным интерфейсом, а не на стороне класса.
Для этого вам implementation
класс должен наследовать от вашего interface
класс, таким образом, реализация будет принята, но, как сказано выше, наследование от несвязанного класса, имеющего реализацию для абстрактной функции, не означает, что реализованная функция должна рассматриваться как реализация абстрактной функции.