C++虚函数(三)

news/2024/7/4 9:23:13 标签: c++, class, 设计模式, vector, delete, c
cle class="tags" href="/tags/CLASS.html" title=class>class="baidu_pl">
cle_content" class="tags" href="/tags/CLASS.html" title=class>class="article_content clearfix">
content_views" class="tags" href="/tags/CLASS.html" title=class>class="htmledit_views">

三. 虚函数使用技巧

3.1 private的虚函数
  考虑下面的例子:


class="tags" href="/tags/CLASS.html" title=class>class A
{
public:
void foo() { bar();}
private:
virtual void bar() { ...}
};

class="tags" href="/tags/CLASS.html" title=class>class B: public A
{
private:
virtual void bar() { ...}
};

  在这个例子中࿰c;虽然bar()在A类中是private的࿰c;但是仍然可以出现在派生类中࿰c;并仍然可以与public或者protected的虚函数一样产生多态的效果。并不会因为它是private的࿰c;就发生A::foo()不能访问B::bar()的情况࿰c;也不会发生B::bar()对A::bar()的override不起作用的情况。

  这种写法的语意是:A告诉B࿰c;你最好override我的bar()函数࿰c;但是你不要管它如何使用࿰c;也不要自己调用这个函数。

3.2 构造函数和析构函数中的虚函数调用
  一个类的虚函数在它自己的构造函数和析构函数中被调用的时候࿰c;它们就变成普通函数了࿰c;不“虚”了。也就是说不能在构造函数和析构函数中让自己“多态”。例如:
class="tags" href="/tags/CLASS.html" title=class>class A
{
public:
A() { foo();} // 在这里࿰c;无论如何都是A::foo()被调用!
~A() { foo();} // 同上
virtual void foo();
};

class="tags" href="/tags/CLASS.html" title=class>class B: public A
{
public:
virtual void foo();
};

void bar()
{
A * a = new B;
class="tags" href="/tags/DELETE.html" title=delete>delete a;
}

  如果你希望class="tags" href="/tags/DELETE.html" title=delete>delete a的时候࿰c;会导致B::foo()被调用࿰c;那么你就错了。同样࿰c;在new B的时候࿰c;A的构造函数被调用࿰c;但是在A的构造函数中࿰c;被调用的是A::foo()而不是B::foo()。

3.3 多继承中的虚函数 3.4 什么时候使用虚函数
  在你设计一个基类的时候࿰c;如果发现一个函数需要在派生类里有不同的表现࿰c;那么它就应该是虚的。从设计的角度讲࿰c;出现在基类中的虚函数是接口࿰c;出现在派生类中的虚函数是接口的具体实现。通过这样的方法࿰c;就可以将对象的行为抽象化。

  以class="tags" href="/tags/SheJiMoShi.html" title=设计模式>设计模式[2]中Factory Method模式为例࿰c;Creator的factoryMethod()就是虚函数࿰c;派生类override这个函数后࿰c;产生不同的Product类࿰c;被产生的Product类被基类的AnOperation()函数使用。基类的AnOperation()函数针对Product类进行操作࿰c;当然Product类一定也有多态(虚函数)。

另外一个例子就是集合操作࿰c;假设你有一个以A类为基类的类层次࿰c;又用了一个std::class="tags" href="/tags/VECTOR.html" title=vector>vector来保存这个类层次中不同类的实例指针࿰c;那么你一定希望在对这个集合中的类进行操作的时候࿰c;不要把每个指针再cast回到它原来的类型(派生类)࿰c;而是希望对他们进行同样的操作。那么就应该将这个“一样的操作”声明为virtual。

  现实中࿰c;远不只我举的这两个例子࿰c;但是大的原则都是我前面说到的“如果发现一个函数需要在派生类里有不同的表现࿰c;那么它就应该是虚的”。这句话也可以反过来说:“如果你发现基类提供了虚函数࿰c;那么你最好override它”。

附:C++中的虚函数和纯虚函数用法

  1.虚函数和纯虚函数可以定义在同一个类(class="tags" href="/tags/CLASS.html" title=class>class)中࿰c;含有纯虚函数的类被称为抽象类(abstract class="tags" href="/tags/CLASS.html" title=class>class)࿰c;而只含有虚函数的类(class="tags" href="/tags/CLASS.html" title=class>class)不能被称为抽象类(abstract class="tags" href="/tags/CLASS.html" title=class>class)。

  2.虚函数可以被直接使用࿰c;也可以被子类(sub class="tags" href="/tags/CLASS.html" title=class>class)重载以后以多态的形式调用࿰c;而纯虚函数必须在子类(sub class="tags" href="/tags/CLASS.html" title=class>class)中实现该函数才可以使用࿰c;因为纯虚函数在基类(base class="tags" href="/tags/CLASS.html" title=class>class)
只有声明而没有定义。

  3.虚函数和纯虚函数都可以在子类(sub class="tags" href="/tags/CLASS.html" title=class>class)中被重载࿰c;以多态的形式被调用。

  4.虚函数和纯虚函数通常存在于抽象基类(abstract base class="tags" href="/tags/CLASS.html" title=class>class -ABC)之中࿰c;被继承的子类重载࿰c;目的是提供一个统一的接口。

  5.虚函数的定义形式:virtual {method body} ;纯虚函数的定义形式:virtual { } = 0; 在虚函数和纯虚函数的定义中不能有static标识符࿰c;原因很简单࿰c;被static修饰的函数在编译时候要求前期bind,然而虚函数却是动态绑定(run-time bind)࿰c;而且被两者修饰的函数生命周期(life recycle)也不一样。

  6.如果一个类中含有纯虚函数࿰c;那么任何试图对该类进行实例化的语句都将导致错误的产生࿰c;因为抽象基类(ABC)是不能被直接调用的。必须被子类继承重载以后࿰c;根据要求调用其子类的方法。

  以下为一个简单的虚函数和纯虚寒数的使用演示࿰c;目的是抛砖引玉!


#include
//father class="tags" href="/tags/CLASS.html" title=class>class
class="tags" href="/tags/CLASS.html" title=class>class Virtualbase
{
public:
virtual void Demon()= 0; //prue virtual function
virtual void Base() {cout<<"this is farther class="tags" href="/tags/CLASS.html" title=class>class"<};
//sub class="tags" href="/tags/CLASS.html" title=class>class
class="tags" href="/tags/CLASS.html" title=class>class SubVirtual :public Virtualbase
{
public:
void Demon() { cout<<" this is SubVirtual!"< void Base() {
cout<<"this is subclass="tags" href="/tags/CLASS.html" title=class>class Base"<};
/* instance class="tags" href="/tags/CLASS.html" title=class>class and sample */
void main()
{
Virtualbase* inst = new SubVirtual(); //multstate pointer
inst->Demon();
inst->Base();
// inst = new Virtualbase();
// inst->Base()
return ;
}

 


本文来自CSDN博客࿰c;转载请标明出处:http://blog.csdn.net/dchcuckoo/archive/2005/10/14/504004.aspx

cle>

http://www.niftyadmin.cn/n/1737976.html

相关文章

TensorFlow2.X绘制常见图像(如AUC,acc,recall等等)

前人已写&#xff0c;所以不重复造轮子了&#xff0c;顾粘上相关链接&#xff1a; https://www.freesion.com/article/5668431209/#METRICS_7 解释一下代码中用到的color colors[0]&#xff0c;需要自定义相关颜色的列表&#xff0c;这里我们可以定义为&#xff1a; colors…

Keras中那些学习率衰减方法

(43条消息) Keras中那些学习率衰减策略_Siucaan-CSDN博客

常用脚本汇总

随机访问文件中的位置&#xff0c;但是需要保证不取到重复的数值 awk { print rand(),$1 } file.txt|sort -k1 |awk { print $2 } >result.txt awk { print rand(),$1 } file.txt在第一列加上随机数 awk { print rand(),$1 } file.txt|sort -k1按照第一列随机数排序 awk { p…

tensorflow2.x训练模型出现nan

1.报如下错误&#xff1a; tensorflow.python.framework.errors_impl.InvalidArgumentError: assertion failed: [predictions must be > 0] [Condition x > y did not hold element-wise:] [x (sub_2:0) ] [[-nan][-nan][-nan]...] [y (Cast_2/x:0) ] [0][[{{node a…

损失函数softmax_cross_entropy、binary_cross_entropy、sigmoid_cross_entropy之间的区别与联系

cross_entropy-----交叉熵是深度学习中常用的一个概念&#xff0c;一般用来求目标与预测值之间的差距。 在介绍softmax_cross_entropy&#xff0c;binary_cross_entropy、sigmoid_cross_entropy之前&#xff0c;先来回顾一下信息量、熵、交叉熵等基本概念。 ----------------…

NetLog 大规模应用实战:Database-sharding 技术

一、背景 Netlog是一家社交网站社区&#xff0c;目前拥有大规模的应用数据&#xff0c;包括&#xff1a; 超过4000w的活跃用户数、每个月5000w的UV、每月50亿的PV、每月60亿的在线时长、支持26中语言&#xff0c;覆盖5个主要的欧洲国家&#xff0c;如意大利、德国&#xff0c;土…

0-1Loss、Cross Entropy Loss、Hinge Loss、Exponential Loss、Modified Huber Loss 等几种常见损失函数的比较

前言 在监督式机器学习中&#xff0c;无论是回归问题还是分类问题&#xff0c;都少不了使用损失函数&#xff08;Loss Function&#xff09;。**损失函数&#xff08;Loss Function&#xff09;**是用来估量模型的预测值 f(x) 与真实值 y 的不一致程度。若损失函数很小&#x…

Heroku的架构

很早之前在Infoq上看到Heroku的介绍&#xff0c;不过当时这个网站并没有推出&#xff0c;今天在整理收藏夹的时候发现&#xff0c;Heroku已经推出一段时间&#xff0c;而且现在作为云计算平台已经有很快的发展了。 Heroku是Rails应用最简单的部署平台。只是简单的把代码放进去&…