Параметр значения по умолчанию в чисто виртуальной функции - PullRequest
0 голосов
/ 13 ноября 2018

Я отправил код как:

Абстрактный класс:

virtual void someFunction(std::vector<someObject*> & iObject) = 0;
virtual void someFunction(std::vector<someObject*> & iObject, bool aSwitch) = 0;

Первая функция существовала, я добавил вторую, чтобы избежать использования параметра значения по умолчанию в чистом методе.

Заголовок в производном классе:

virtual void someFunction(std::vector<someObject*> & iObject);
virtual void someFunction(std::vector<someObject*> & iObject, bool aSwitch = false);

Использование как ожидалось:

someFunction(std::vector<someObject*> & Object);

или

someFunction(std::vector<someObject*> & Object, true);

someFunction, как это было - уже существовало, я добавил переключатель. Это хорошо работает, но я в замешательстве.

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

Вызывает ли это двусмысленность, если я добавлю значение по умолчанию, и если да, понадобится ли мне значение по умолчанию в производном виртуальном методе?

Могу ли я просто добавить значение по умолчанию в чисто виртуальной функции и покончить с первой функцией в заголовке производного класса? Какова лучшая практика здесь?

1 Ответ

0 голосов
/ 16 ноября 2018

Аргументы по умолчанию в целом

Аргументы по умолчанию для функций связаны не с самой функцией, а с контекстом вызова : значения по умолчанию, объявленные для функции в области действия, в которой онабудет вызван (см. стандарт C ++, [dcl.fct.default]).Для пример :

void f(int a=1);     // forward declaration with a default value for the compilation unit
void f(int a)        // definition 
{
    cout<<a<<endl; 
}
void g() {
    void f(int a=2);  // declaration in the scope of g
    f();
}
int main() {
    f();            // uses general default => 1
    g();            // uses default defined in g => 2
    return 0;
}

Аргументы по умолчанию для виртуальных функций

Эта логика применяется ко всем функциям, а также к чисто виртуальным функциям.Единственное, что рассматриваемое объявление функции (и ее значения по умолчанию) является классом объектов, известным компилятору.Таким образом, одна и та же функция одного и того же объекта может иметь разные аргументы по умолчанию в зависимости от типа объекта, используемого для ее вызова.Для пример :

struct A {
    virtual void f(int a=1) = 0;    
};
struct B:A {
    void f(int a) override ;     
};
struct C:A {
    void f(int a=2) override ;     
};

void B::f(int a)        // definition 
{
    cout<<"B"<<a<<endl; 
}
void C::f(int a)        // definition 
{
    cout<<"C"<<a<<endl; 
}

int main() {
    B b; 
    C c; 
    A *x=&c, *y=&b;    // points to the same objects but using a polymorphic pointer
    x->f();  // default value defined for A::f() but with the implementation of C ==> C1   
    y->f();  // default value defined for A::f() but with the implementation of B ==> B1
//  b.f();  // default not defined for B::f() so cannot compile   
    c.f();  // default value defined for C::f(); ==> C2
}

Полезно знать

  • Аргументы по умолчанию не изменяют сигнатуру функции.Это все та же функция.
  • Различные аргументы по умолчанию не влияют на правило ODR.Таким образом, вы можете использовать разные значения по умолчанию в разных единицах компиляции, и это все равно будет одной и той же функцией.
  • Аргументы по умолчанию предоставляются вызывающей стороной, а не самой функцией
  • Если для базовых и производных классов определены разные аргументы по умолчанию, вам необходимо быть предельно осторожным, поскольку могут быть разные значения по умолчанию.используется в зависимости от того, как вы вызываете функцию.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...