我想了解虚函数的用途。
让我们分析一下成员函数是非虚拟的代码:
示例1:
struct A
{
void foo1() { cout << "foo 1 from A \n"; }
};
struct B : A
{
void foo1() { cout << "foo 1 from B \n"; }
};
int main()
{
A *a = new B;
a->foo1(); // will print "foo 1 from A \n" because A::foo1 isn't virtual
B *b = new B;
b->foo1(); // will print "foo 1 from B \n"
}
我们看到a->foo1()
的输出;将是“foo 1 from A”但我希望函数B执行自己的foo1
函数。所以我必须覆盖它并使A::foo1
虚函数。
示例2:
struct A
{
virtual void foo1() { cout << "foo 1 from A \n"; }
};
struct B : A
{
void foo1() { cout << "foo 1 from B \n"; }
};
int main()
{
A *a = new B;
a->foo1(); // will print "foo 1 from B \n"
B *b = new B;
b->foo1(); // will print "foo 1 from B \n"
}
现在A::foo1
已被覆盖,a->foo1()
按照我们的要求打印“来自B的foo 1”。但是,让我们考虑一下B类具有A:
示例3:
struct A
{
int a;
void foo1() { cout << "foo 1 from A \n"; }
};
struct B : A
{
int b;
void foo1() { cout << "foo 1 from B \n"; }
void foo2() { cout << "foo 2 from B \n"; }
};
int main()
{
A *a = new B;
// a->foo2(); // compiler error, a doesn't see foo2 function
a->foo1();
// a->b = 1; // compiler error, a doesn't see member variable b
a->a = 1;
// We aren't going to do B *b = new A; here because that's nonsense
B *b = new B;
b->foo2(); // ok
b->foo1(); // ok
b->b = 1; // ok
b->a = 1; // ok
}
正如我们现在看到的,B不是A的精确副本;它继承了A并用一些新函数和变量扩展它。我们无法a->foo2()
或a->b
。
我认为A *a = new B;
这样的陈述在阅读或分析代码时要比B *b = new B;
更加混乱。
我知道b
是指向B实例的指针。想知道A*
指向的对象类型是什么并不困惑吗?
所以我的问题是:我们可以使用虚拟函数吗?
如果基类中没有变量或函数,我不会将它用于派生类。使用B *b = new B;
创建新对象更加清晰,而不是A *a = new B;
。
当我使用B *b = new B;
创建B的实例时,A的成员函数不需要是虚拟的,因为B将使用自己的A::foo1
自动覆盖foo1
。
因此,我认为虚拟函数的唯一用途是我们想要在运行时更改功能。
在我们想要在运行时更改已执行的类时,它可能在这种情况下有用:
A *a;
B b;
C c;
a = &B;
a->foo1();
a = &C;
a->foo1();
或者,在将参数传递给函数时,这可能很有用:
void execute(A *a)
{
a->foo1();
}
我错过了一些关于此的事情吗?
答案 0 :(得分:3)
虚函数是C ++实现运行时多态的主要方式。 Google搜索多态可能会向您展示该技术的用处。
答案 1 :(得分:0)
虚函数是C ++实现多态性概念的方式。
在C ++中,简单方法重载用于编译时多态,其中编译器在编译期间绑定方法。
如果是虚函数,编译器将在运行时和需要时使用这些方法。