2013-09-07 2 views
2

У меня есть вопрос о реализации интерфейса в C++:реализация интерфейса с дополнительными аргументами по умолчанию?

Предположим, есть интерфейс:

class A 
{ 
virtual void f() = 0; 
}; 

При реализации этого, я задаюсь вопросом, есть ли способ сделать что-то вроде:

class B : public A {  
    void f(int arg=0) {....} // unfortunately it does not implement f() this way 
}; 

Я хочу сохранить чистоту. Когда клиентский код вызывает через открытый интерфейс A, arg всегда устанавливается в 0 автоматически. Однако, когда я называю это через B, у меня есть гибкость, чтобы называть его с помощью arg, установленного на другое значение. Это достижимо?

EDIT: Поскольку я контролирую интерфейс и реализацию, я открыт для любых предложений, макросов, шаблонов, функторов или чего-либо еще, что имеет смысл. Я просто хочу иметь минимальную и чистую базу кода. Класс большой, и я не хочу писать код, который не является абсолютно необходимым - например. другая функция, которая просто переходит к фактической реализации.

EDIT2: Просто хочу немного разъяснить: публичный интерфейс предоставляется клиенту. Он более ограничительный, чем интерфейс класса B, который используется только внутренне. Однако функция f() по существу делает то же самое, кроме незначительного различного лечения, основанное на входном аргументе. Реальный класс имеет довольно некоторые интерфейсные функции, а подпись сложна. Выполнение пересылки функций быстро приводит к утомительному повторению кода, и оно загрязняет внутренний интерфейс для B. Интересно, как лучше всего справиться с этим в C++.

Спасибо!

ответ

2

Да, как раз две отдельные функции:

class B : public A {  
    void f() { return f(0); } 
    void f(int arg) { .... } 
}; 
+0

Да, это сработает. Однако это большой класс, и, фактически, я должен добавить много пересылающих членов в B, что делает его очень загроможденным. Я стараюсь избегать этого. – ttrrxx

+0

@ttrrxx: вы не можете переопределить функцию с помощью функции, которая, к сожалению, принимает разные аргументы. Это включает функции аргументов по умолчанию. Если это касается вас, вы можете написать макрос, чтобы написать для вас участников пересылки. – nneonneo

+0

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

2

Если у вас есть интерфейс, основной принцип должен быть, что функция всегда принимает те же аргументы и ВСЕГДА работает таким же образом, независимо от того, что в производный класс. Добавление дополнительных аргументов недопустимо, потому что это предполагает, что «вещь», которая работает на объекте, «знает», что аргумент/делает.

Есть несколько способов решения этой проблемы - Тр, что весной на ум сразу же являются:

  1. Добавьте аргумент в интерфейсе/BaseClass.
  2. Не используйте аргумент, но некоторые дополнительные функции, которые [когда производный объект создан или какое-либо другое место, которое «знает разницу»], хранит дополнительную информацию внутри требуемого объекта.
  3. Добавьте еще один класс, который «знает», что аргумент находится внутри класса.

Примером второго будет:

class B: public A 
{ 
    private: 
    int x; 
    public: 
    B() x(0) { ... } // default is 0. 
    void f() { ... uses x ... } 
    void setX(int newX) { x = newX; }; 
    int getX() { return x; } 
}; 

Итак, когда вы хотите использовать x с другим значением, чем ноль, вы называете bobject->setX(42); или что-то подобное.

+0

Проблема в том, что мне нужно обеспечить выполнение клиентских вызовов из интерфейса. Всегда имеет значение arg, равное 0. Если x случайно установлено на 1 через внутренний интерфейс B, тогда клиентский доступ к f() будет иметь значение arg, равное 1, которое будет Плохо. – ttrrxx

0

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

class BImpl { 
public: 
    doF(int arg); 
}; 

class B : public A { 
    BImpl impl; 
public: 
    virtual void f() override { 
    impl.doF(0); 
    } 
}; 
0

Выполнение функции переадресации быстро приводит к утомительной повторения кода, и это загрязняет внутренний интерфейс для B. Интересно, что это лучший способ справиться с этим в C++.

Похоже, вам нужно написать сценарий для автоматизации части процесса.

Смежные вопросы