Я указал this question (я сменил название). Я знаю, что генерация кода, связанная с virtual
, специфична для реализации. Однако более ранний вопрос предполагает, что при вызове метода не виртуального базиса существует дополнительная стоимость, связанная с наследованием virtual
.Есть ли дополнительная стоимость вызова не виртуальных базовых методов в виртуальном наследовании?
я написал следующие тестовые коды и проверил его сборку в г ++ (с -O4
):
Общей частью
struct Base {
int t_size;
Base (int i) : t_size(i) {}
virtual ~Base() {}
int size() const { return t_size; };
};
struct D1 : virtual Base {
int a[10];
D1() : Base(0) {}
~D1() {}
};
struct D2 : virtual Base {
int a[20];
D2() : Base(0) {}
~D2() {}
};
...
void foo (Base *p)
{
if(p->size())
return;
p = 0;
}
int main()
{
Derived d;
foo(&d);
}
Теперь разница части здесь:
Код 1 (нормальное наследование)
struct Derived : Base {
Derived() : Base(0) {}
~Derived() {}
int a[100];
};
Код 2 (виртуальное наследование)
struct Derived : virtual Base {
Derived() : Base(0) {}
~Derived() {}
int a[100];
};
код 3 (множественное виртуальное наследование)
struct Derived : D1, D2 {
Derived() : Base(0) {}
~Derived() {}
int a[100];
};
Когда я проверил его сборку, есть без разницы между всеми 3 версиями. И Ниже приведен код сборки:
.file "virtualInheritFunctionCall.cpp"
.text
.p2align 4,,15
.globl _Z3fooP4Base
.type _Z3fooP4Base, @function
_Z3fooP4Base:
.LFB1:
.cfi_startproc
rep
ret
.cfi_endproc
.LFE1:
.size _Z3fooP4Base, .-_Z3fooP4Base
.section .text.startup,"ax",@progbits
.p2align 4,,15
.globl main
.type main, @function
main:
.LFB2:
.cfi_startproc
xorl %eax, %eax
ret
.cfi_endproc
.LFE2:
.size main, .-main
.ident "GCC: (Ubuntu/Linaro 4.6.1-9ubuntu3) 4.6.1"
.section .note.GNU-stack,"",@progbits
Означает ли это, что virtual
наследование не имеет каких-либо дополнительных затрат, когда определенная оптимизация ON? Нужно ли мне выполнять более сложный тестовый код, чтобы оценить это? Обратите внимание, что без оптимизации существует разница между этими сборками.
Какой смысл окончательного 'p = 0;'? 'p' - это только локальная переменная. Кроме того, 'Base' является стандартным макетом, а' D1' и 'D2' пусты, поэтому неудивительно, что есть место для оптимизации. –
Я ожидал бы, что любая дополнительная стоимость придет, когда вы вызываете не виртуальную функцию 'size' через' Derived * ', а не когда вы вызываете ее через' Base * '. Тип 'Base' не знает, действительно ли какой-либо другой класс наследует его, поэтому нет никакого способа, чтобы фактически наследование от« Base »могло привести к накладным расходам при вызове функции в« Base »с помощью указателя на« Base » , –
@SteveJessop, отсутствие разницы в результатах сборки при проверке с помощью 'Derived *'. Я выбираю 'Base *' в контексте более раннего вопроса, где принятый ответ подсказывает это. @Kerrek, я просто написал 'p = 0', так что компилятор не оптимизирует условие' if'. Ничего особенного. – iammilind