一根老葱(17757899) 15:00:29 例如一个类 class A { public: virtual void foo() { cout << "A::foo() is called" << endl;} }; 这个class A是一个基类 然后呢:我派生一个B class B: public A { public: virtual void foo() { cout << "B::foo() is called" << endl;} }; 问问大家 A * a = new B(); a->foo(); 这里的 a->foo(); 是哪个? 一根老葱(17757899) 15:03:02 这里的 a->foo(); 看起来呢是调用基类的 foo() 其实呢是调用 class B 的foo() //============================// 一根老葱(17757899) 15:06:39 void fun(A * a) { a->foo(); // 被调用的是A::foo() 还是B::foo()? } 一根老葱(17757899) 15:08:44 因为foo()是个虚函数,所以在fun这个函数中, 只根据这段代码, 无从确定这里被调用的是A::foo()还是B::foo(), 但是可以肯定的说:如果a指向的是A类的实例,则A::foo()被调用, 如果a指向的是B类的实例,则B::foo()被调用。 这种同一代码可以产生不同效果的特点,被称为“多态”。 他是根据实际指针来绝定动作的 一根老葱(17757899) 15:13:08 纯虚函数 也说说把 class A { public: virtual void foo()=0; // =0标志一个虚函数为纯虚函数 }; 这个时候 就是声明为纯虚 纯虚函数的意思是:我是一个抽象类! 不要把我实例化!纯虚函数用来规范派生类的行为, 实际上就是所谓的“接口”。它告诉使用者, 我的派生类都会有这个函数 一根老葱(17757899) 15:15:18 析构函数也可以是虚的,甚至是纯虚的 当一个类打算被用作其它类的基类时,它的析构函数必须是虚的。 记住这些就差不多了 构造函数不能是虚的 一根老葱(17757899) 15:19:39 在你设计一个基类的时候,如果发现一个函数需要在派生类里有不同的表现, 那么它就应该是虚的。从设计的角度讲,出现在基类中的虚函数是接口, 出现在派生类中的虚函数是接口的具体实现。通过这样的方法, 就可以将对象的行为抽象化 其实新人不该叫 虚函数 虚函数 翻译的不好 我喜欢叫虚函数为虚拟函数 虚拟一个动作 一根老葱(17757899) 15:44:13 1.虚函数仅适用于有继承关系的类对象, 所以只有类的成员函数才能说明为虚函数. 2.静态成员函数不能是虚函数. 3.内联函数不能是虚函数. 4.构造函数不能是虚函数. 5.析构函数可以是虚函数. 虚函数最主要的缺点是执行效率较低 原因是: 编译器发现一个类中有虚函数,编译器会立即为此类生成虚拟函数表 VTABLE. 虚拟函数表的各表项为指向对应虚拟函数的指针。 编译器在此类中隐含插入一个指针VPTR 在调用此类的构造函数时,在类的构造函数中,编译器会隐含执行VPTR与VTABLE的关联代码, 将VPTR指向对应的VTable。这就将类与此类的VTABLE联系了起来。 实现机制导致了高灵活性低效率 */ |
老葱讲座
最新推荐文章于 2025-01-21 21:01:46 发布
1万+

被折叠的 条评论
为什么被折叠?



