Редактировать: В некоторых комментариях под простым я подразумеваю: а) меньше кода, б) легко поддерживать и в ) трудно ошибиться.
Правка №2: Кроме того, использование включения вместо частного наследования не вызывает возражений, если оно действительно упрощает реализацию InterfaceImpl
.
В настоящее время я знаю, что единственный способ сделать это - поручить разработчику определить абстрактный метод и делегировать вызов методу целевого базового типа. Пример:
#include <iostream>
#include <memory>
class Interface
{
public:
virtual void method1() = 0;
virtual void method2(int x) = 0;
};
class MethodOneImpl
{
private:
void method1(int x)
{ std::cout << "MethodOneImpl::method1() " << x << std::endl; }
public:
void method1() { method1(0); }
};
class MethodTwoImpl
{
public:
void myFunc(int x)
{ std::cout << "MethodTwoImpl::myFunc(x)" << x << std::endl; }
};
class InterfaceImpl : public Interface
, private MethodOneImpl
, private MethodTwoImpl
{
public:
virtual void method1() { MethodOneImpl::method1(); }
virtual void method2(int x) { MethodTwoImpl::myFunc(x); }
};
int main()
{
std::unique_ptr<Interface> inf;
inf.reset(new InterfaceImpl);
inf->method1();
inf->method2(0);
// This should be disallowed!
// std::unique_ptr<MethodOneImpl> moi;
// moi.reset(new InterfaceImpl);
}
Сначала я подумал, что, возможно, это может решить проблему:
class InterfaceImpl : public Interface
, private MethodOneImpl
, private MethodTwoImpl
{
public:
using MethodOneImpl::method1;
// Obviously this wouldn't work as the method names don't match.
//using MethodTwoImpl::???
};
Первый оператор using сделает оба метода MethodOneImpl :: method1
общедоступными, но на самом деле он не выполняет контракт с Интерфейсом
, и он изменяет доступность MethodOneImpl :: method1 (int)
. И, очевидно, мы не могли использовать это решение с method2
, поскольку имена не совпадают.
FWIW, у меня есть то, что я считаю решением, но оно вообще не является частью стандарта (другими словами, оно не компилируется). Я подумывал внести предложение в комитет по C ++; Если у кого-то есть совет, я был бы признателен за любые комментарии ниже (но, пожалуйста, не отправляйте совет в качестве ответа).