2015-01-24 3 views
0

Пожалуйста, не бейте меня или не говорите, что я ошибаюсь, задавая этот вопрос или что множественное наследование является злым. Этот вопрос заключается в том, чтобы лучше понять, как работают компиляторы C++. Я знаю, что оператор inline используется, чтобы намекнуть компилятору заменить вызов функции исходным кодом, который имеет каждый параметр с или не встраивать функцию. Если бы вы могли принудительно выполнить функцию inline, это было бы здорово, но это не проблема, которую я пытаюсь решить. Я хочу сделать, чтобы создать один кусок кода, который написан в одном месте, и копировать и вставлять в другие места сограждан. Код двутавровых записи будет выглядеть примерно так:Как встроить виртуальный с множественным наследованием

struct base 
{ 
    virtual double eval() = 0; // should be no eval function for the 
}; 

struct foo : public base 
{ 
    virtual double eval() overrides 
    { 
      return //foo eval 
    } 
}; 

struct bar : public base 
{ 
    virtual double eval() overrides 
    { 
      return //foo eval 
    } 
}; 

struct baz : public base 
{ 
    virtual double eval() overrides 
    { 
      return //baz eval 
    } 
}; 

struct FooBarBaz : public foo, public bar, public baz 
{ 
    virtual double eval() final 
    { 
      return foo::eval() + bar::eval() + baz::eval(); 
    } 
}; 

компилятор будет генерировать что-то, что эквивалентно следующему:

struct base 
{ 
    virtual double eval() = 0; // should be no eval function for the 
}; 

struct foo : public base 
{ 
    virtual double eval() overrides 
    { 
      return //foo eval 
    } 
}; 

struct bar : public base 
{ 
    virtual double eval() overrides 
    { 
      return //foo eval 
    } 
}; 

struct baz : public base 
{ 
    virtual double eval() overrides 
    { 
      return //baz eval 
    } 
}; 

struct FooBarBaz : public foo, public bar, public baz 
{ 
    virtual double eval() final 
    { 
      return /*foo eval*/ + /*bar eval*/ + /*baz eval*/ 
    } 
}; 

мне сказали, что использование <type_traits> является способ решить эту проблему, если это правда, я хотел бы знать, как получить желаемые результаты. если я не хотел бы знать, как сделать это

+2

Знаете ли вы, что компилятор уже выполняет то, что вы хотите? Вы пытались установить уровни оптимизации, а затем посмотрели листинг на ассемблере? –

+1

Простите мое невежество, но как это сделать вы представляете код 'inlined' от работы по-разному с множественным наследованием? –

+0

Я нейтрально отношусь к комплитеру и хорошо разбираюсь в языке ассемблера. Что касается кода 'inline', то компилятор возьмет код от использования кода от вызова базовой функции и вставляет код в производную функцию вместо перехода через v-таблицу для поиска функции –

ответ

1

ли решает компилятор встраивать или не до эвристики он закодированный ... но нет никакой причины, почему он не должен встраивать вызовы к foo::eval, bar::eval и baz::eval от FooBarBaz::eval, так как квалификация отключает динамическую отправку.

То есть, когда компилятор встречается с квалифицированным вызовом foo::eval, он выполнит окончательный переопределитель для этой функции-члена a с уровнем foo. Он не будет использовать vtable (который будет в конечном итоге в бесконечной рекурсии в любом случае, так как конечный подмены будет FooBarBaz::eval.

Кроме этого, вы должны прочитать о виртуального наследования, то FooBarBaz имеет подобъектов типа base, возможно, не то, что вы хотите ...

+0

Мне нравится, что вы отвечаете, однако функция' base' является чистой абстрактной функцией только для обеспечения стандартного интерфейса без каких-либо реализации или данных ко всем производным объектам и, следовательно, виртуальное наследование не имеет смысла, если мне не понадобится виртуальное наследование, чтобы позволить правообладателю правильно. –

+0

@ vickoza: 'FooBarBaz fbz; base & b = fbz'.Ошибка: неоднозначное преобразование, поскольку существует более чем одна «база», которую вы хотите связать? * Пустые * базы, используемые в качестве интерфейсов, являются первыми кандидатами на «виртуальное» наследование: если есть полный объект, и это происходит для реализации того же интерфейса через разные пути наследования, это нормально, есть только один объект *, который реализует протокол. –

+0

Спасибо, я понимаю, что я думал, что виртуальное наследование сливает базовую реализацию, поэтому у вас есть только одна база, если у вас есть много объектов, которые имеют одну и ту же базу, так что вы говорите, что я точно определяю 'struct FooBarBaz: public virtual foo, public virtual bar, public virtual baz', если это так, чем при использовании наследования, всегда полезно использовать виртуальное наследование –

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