наследование — путаница с виртуальной функцией c ++

Я изучаю виртуальные функции, и я очень запутался с результатами нижеприведенной программы
Я надеялся, что оба a1.virFun(b1) а также b1.virFun(b1) должен вернуть «привет от B», но программа возвращает «привет от A». Это противоречит моему пониманию. Можете ли вы объяснить, почему b1.sayHello() не вызывается, даже когда я передаю b1 в качестве аргумента и b1.sayHello() это виртуальная функция.

#include<iostream>

using namespace std;

class A
{
public:
virtual void sayHello();
void virFun(A obj);

};

class B : public A
{
public:
void virFun(A obj);
virtual void sayHello();

};

void A::sayHello()
{
cout << "hello from A" << endl;
}

void B::sayHello()
{
cout <<"hello from B" << endl;
}

void A::virFun(A obj)
{
obj.sayHello();
}

void B::virFun(A obj)
{
obj.sayHello();
}

int main()
{
A a1;
B b1;

a1.virFun(b1);
b1.virFun(b1);

return 0;
}

3

Решение

Заставьте virFun брать ссылку, а не объект по значению:

 void A::virFun(A& obj) { obj.sayHello(); }

причина: Если вы берете A по значению, параметр будет инициализирован путем создания копии переданного значения. Если вы передадите B, он скопирует часть «A» в новую переменную типа параметра (A) — это известно как нарезка объектов. Параметр больше не будет «be-a» B например, он будет вести себя как A Например, хорошо.

Нет необходимости переопределять virFun в классе B, так как он использует аргумент obj в обоих случаях

На самом деле virFun может быть статической функцией. Название сбивает с толку, так как это даже не virFun (виртуальная функция) — это обычная функция, которая использования виртуальная функция.

#include<iostream>

using namespace std;

struct A     { virtual     void sayHello() { cout << "hello from A" << endl; } };
struct B : A { /*virtual*/ void sayHello() { cout << "hello from B" << endl; } };

static void virFun(A& obj)
{
obj.sayHello();
}

int main()
{
A a1;
B b1;

virFun(a1);
virFun(b1);
}

Смотрите это в прямом эфире http://liveworkspace.org/code/1624496ced29eb4683f5b19072f72f60

hello from A
hello from B
3

Другие решения

void virFun(A obj);

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

void virFun(const A &obj);
void virFun(const A *obj);

Иначе virFun() получит копия вашего объекта, который заканчивается «Нарезка» это и потеря информации производного класса. Копия имеет Avtable и отсутствует Bдополнительные поля. Обычно это катастрофа.

Как правило, передавайте объекты, используя T& или же const T& а не простой T, Помимо проблемы нарезки, она также более эффективна.

6

По вопросам рекламы [email protected]