C++一些疑惑!

对象本体: 可以理解为一个对象类型,如类 类型(就是 class  定义) 
对象实体:可以理解为一个对象实例,就是用这个类型定义的一个变量 ...      
可以操作的是对象实体(实例),它才是一个有效的变量   ~   
对象本体   只是一个类型   .....
例如
class   A   
  {   
  }   
  A   a;   

 这里A是本体,a是实体

==================================================================

与类名称具有一样名称的成员函数是构造函数。构造函数不能有返回值,甚至不能有return语句。说明一个有返回值的构造函数是错误的,取构造函数的地址也是错误的。 
如果一个类有构造函数,在程序中每个该类类型的对象在使用之前由此构造函数进行初始化(有关初始化的更多信息参见本章后面的“用特殊成员函数进行初始化”)。

构造函数是在对象的创建点上被调用的。创建对象可以是:

* 全局对象(文件范围或外部链接的)。

* 在一个函数或者小的封闭块中的局部变量。

* 用new运算符创建的动态对象。new操作在程序的堆或自由存储区中分配一个对象。

* 因显式调用构造函数而创建的临时对象(详见本章后面的“临时对象”)。

* 因编译器隐含调用构造函数而创建的临时对象(详见本章后面的“临时对象”)。

* 其它类的数据成员。在创建类类型的对象时,若此类类型由其它类类型变量组成,将会引起该类中每个对象的创建。

* 一个类的基类子对象。创建派生类类型的对象时会引起基类构件的创建。

构造函数的作用

一个构造函数执行各种任务,但对于程序员来说,这些任务是不可见的,你甚至可以不必为构造函数写任何代码。这些任务都同建立一个完全的、正确的类类型对象实例有关。

在MS C++中(同样也在很多其它C++中)一个构造函数:

* 初始化对象的虚拟基指针(vbptr)。如果该类是由虚拟基类派生出的,则这一步要执行。

* 按说明的顺序调用基类和成员的构造函数。

* 初始化对象的虚拟函数指针(vfptr)。如果该类有或者继承了虚拟函数,则这一步要执行,虚拟函数指针指向类的虚拟函数表(v-table),并且使虚拟函数的调用同代码正确绑定(binding)。

* 在构造函数体中执行可选的代码。

当构造函数结束以后,所分配的存储器就是一个给定类类型的对象。因为构造函数执行这些步骤,故虚拟函数的“迟后绑定”形态可以在虚拟函数的调用点得以解决,构造函数也要构造基类以及构造组合对象(作为数据成员的对象),迟后绑定是C++实现对象的多态行为的机制。

说明构造函数的规则

构造函数具有同类名相同的名称。只要遵守重载函数的规则(有关详情参见第12章“重载”),可以说明多个构造函数。

语法

类名称(参量说明表opt) cv-修饰符表opt

C++定义了两种类型的构造函数,缺省的和拷贝的构造函数。如表11.2所述。

表11.2 缺省的和拷贝构造函数

构造函数的种类 参量 目的 
缺省构造函数 可以无参量调用 构造一个类类型的缺省对象 
拷贝构造函数 可以接受对同种类类型的引用作为唯一参量 拷贝类类型的对象 


缺省构造函数不要参量即可调用,但你可以说明一个带有参量表的缺省构造函数,只要让所有的参量有缺省值即可。同样,拷贝构造函数必须接受同一类类型的引用作为唯一参量。但可以提供更多的参量,只要后续的参量具有缺省值即可。

如果你不提供任何构造函数,编译器会试图生成一个缺省的构造函数。同样,如果你没有提供拷贝构造函数,编译器也会试图产生一个。编译器产生的构造函数视为公有的成员函数。如果你说明一个拷贝构造函数,而其第一个参量是一个对象而不是一个引用,则会产生错误。

编译器生成的缺省构造函数建立对象(初始化vftables和vbtables,如前面所述),并调用基类及成员的缺省构造函数,但不会采取其它的行动。基类和成员的构造函数只要存在,是可访问的,并且是无二义性的就会被调用。

编译器生成的拷贝构造函数建立一个对象,并且采用一个成员方式的拷贝来复制要被拷贝的对象的内容。如果基类或成员的构造函数存在,则它们将被调用,否则,就采取位方式的拷贝。

如果所有的基类和该类类型的成员类具有接受一个常量参量的构造函数,则编译器生成的拷贝构造函数接受一个唯一的参量的类型是const type&;否则,编译器生成的拷贝构造函数接受的唯一参量的类型是type &。

你可以用一个构造函数去初始化一个const和volatile对象,但构造函数本身不能说明为const和volatile的。对于构造函数唯一合法的存储类型inline,对于构造函数使用任何其它的存储类修饰符,包括__declspec关键字都会引起错误。构造函数和析构函数除了__stdcall外不能说明为其它的调用约定。


派生类是不能继承基类中的构造函数的。当一个派生类的对象在创建的时候,它是从基类构件开始构造的,然而才进入派生类构件。编译器使用每个基类的构造函数作为完整对象初始化的一部分(除了虚拟派生有所不同,参见本章后面的“初始化基类”)。

显式地调用构造函数

在程序中,为创建给定类型的对象,可以显式地调用构造函数。例如:创建两个Point型对象的描述一条线段的端点,可以写如下代码:

DrawLine(Point(13,22),Point(87,91);

创建了两个Point对象,传递给DrawLine函数,并在该表达式(函数调用)结束后拆除。

另外一个显式地调用构造函数的情况是在一个初始化中:

Point pt=Point(7,11);

创建了一个Point类型的对象,并用接受两个整形参量的构造函数进行初始化。如前面的两个例子中,通过显式地调用构造函数创建的对象是无名的对象,并在它们所创建的表达式中是有生存期的。在本章后面的“临时对象”中将对这一点进行深入的讨论。 在构造函数内调用成员函数和虚拟函数

在构造函数里面调用任何成员函数通常是很安全的,因为在执行第一行用户代码之前,对象已经完全建立起来了(已经初始化了虚表等等)。但是当成员函数调用了其抽象基类的虚拟成员函数时,在构造函数和析构函数调用此成员函数存在着潜在的不安全性。

构造函数可以调用虚拟函数。在调用虚拟函数时,被调用的是在构造函数自身的类中定义的函数(或者从其基类中继承的函数)。下面的例子显示了一个虚拟函数在一个构造函数中被调用时发生的情况。

#include <iostream.h>
class Base
{
public:
Base();//缺省构造函数
virtual void f(); //虚拟成员函数
};
Base::Base()
{
cout<<"Constructing Base sub-object\n ";
f();//在构造函数中调用虚拟成员函数
}
void Base::f()
{
cout<<"called Base::f()\n";
}
class Derived:public Base
{
public:
Derived();//缺省构造函数
void f(); //该类虚拟函数的实现
};
Derived::Derived()
{
cout<<"constructing Derived object\n";
}
void Derived::f()
{
cout<<"Called Derived::f()\n";
}
void main()
{
Derived d;
}
在上面的程序运行的时候,Derived d的说明会引发下列一系列事件:

1. 类Derived的构造函数(Derived::Derived)被调用。

2. 在进入到Derived类的构造体之前,基类Base的构造函数被调用。

3. Base::Base调用函数f,它是一个虚拟函数。通常被调用的函数会是Derived::f,因为对象d是Derived类型的对象。但因为Base::Base是一个构造函数,此时的对象是一个Derived类型的对象,故Base::f将会被调用。

构造函数与数组

数组的构造只能使用缺省的构造函数。缺省构造函数要么不接受任何参量,要么对于它的所有参量都有缺省的值。数组通常是按升序来构造的,该数组的每一个成员的初始化都是使用同一构造函数。

构造的次序

对于派生类或其成员数据是类类型的类,构造发生的顺序有助于你理解,在任一给定的构造函数中你能够使用对象的哪一部分。

构造与继承

一个派生类的对象是从基类到派生类通过按次序为每个类调用构造函数来构造的。

每个类的构造函数能仅依赖于被完全构造好的它的基类。

有关初始化的完整描述,包括初始化的顺序,见本章后面的“初始化基类及成员”。

构造与组合类型

含有类类型数据成员的类称为组合类。当创建一个组合类类型的对象时,含有类的构造函数在该类的构造函数之前调用。 有关这种情况的初始化,见本章后面的“初始化基类及成员”。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
1 目标检测的定义 目标检测(Object Detection)的任务是找出图像中所有感兴趣的目标(物体),确定它们的类别和位置,是计算机视觉领域的核心问题之一。由于各类物体有不同的外观、形状和姿态,加上成像时光照、遮挡等因素的干扰,目标检测一直是计算机视觉领域最具有挑战性的问题。 目标检测任务可分为两个关键的子任务,目标定位和目标分类。首先检测图像中目标的位置(目标定位),然后给出每个目标的具体类别(目标分类)。输出结果是一个边界框(称为Bounding-box,一般形式为(x1,y1,x2,y2),表示框的左上角坐标和右下角坐标),一个置信度分数(Confidence Score),表示边界框中是否包含检测对象的概率和各个类别的概率(首先得到类别概率,经过Softmax可得到类别标签)。 1.1 Two stage方法 目前主流的基于深度学习的目标检测算法主要分为两类:Two stage和One stage。Two stage方法将目标检测过程分为两个阶段。第一个阶段是 Region Proposal 生成阶段,主要用于生成潜在的目标候选框(Bounding-box proposals)。这个阶段通常使用卷积神经网络(CNN)从输入图像中提取特征,然后通过一些技巧(如选择性搜索)来生成候选框。第二个阶段是分类和位置精修阶段,将第一个阶段生成的候选框输入到另一个 CNN 中进行分类,并根据分类结果对候选框的位置进行微调。Two stage 方法的优点是准确度较高,缺点是速度相对较慢。 常见Tow stage目标检测算法有:R-CNN系列、SPPNet等。 1.2 One stage方法 One stage方法直接利用模型提取特征值,并利用这些特征值进行目标的分类和定位,不需要生成Region Proposal。这种方法的优点是速度快,因为省略了Region Proposal生成的过程。One stage方法的缺点是准确度相对较低,因为它没有对潜在的目标进行预先筛选。 常见的One stage目标检测算法有:YOLO系列、SSD系列和RetinaNet等。 2 常见名词解释 2.1 NMS(Non-Maximum Suppression) 目标检测模型一般会给出目标的多个预测边界框,对成百上千的预测边界框都进行调整肯定是不可行的,需要对这些结果先进行一个大体的挑选。NMS称为非极大值抑制,作用是从众多预测边界框中挑选出最具代表性的结果,这样可以加快算法效率,其主要流程如下: 设定一个置信度分数阈值,将置信度分数小于阈值的直接过滤掉 将剩下框的置信度分数从大到小排序,选中值最大的框 遍历其余的框,如果和当前框的重叠面积(IOU)大于设定的阈值(一般为0.7),就将框删除(超过设定阈值,认为两个框的里面的物体属于同一个类别) 从未处理的框中继续选一个置信度分数最大的,重复上述过程,直至所有框处理完毕 2.2 IoU(Intersection over Union) 定义了两个边界框的重叠度,当预测边界框和真实边界框差异很小时,或重叠度很大时,表示模型产生的预测边界框很准确。边界框A、B的IOU计算公式为: 2.3 mAP(mean Average Precision) mAP即均值平均精度,是评估目标检测模型效果的最重要指标,这个值介于0到1之间,且越大越好。mAP是AP(Average Precision)的平均值,那么首先需要了解AP的概念。想要了解AP的概念,还要首先了解目标检测中Precision和Recall的概念。 首先我们设置置信度阈值(Confidence Threshold)和IoU阈值(一般设置为0.5,也会衡量0.75以及0.9的mAP值): 当一个预测边界框被认为是True Positive(TP)时,需要同时满足下面三个条件: Confidence Score > Confidence Threshold 预测类别匹配真实值(Ground truth)的类别 预测边界框的IoU大于设定的IoU阈值 不满足条件2或条件3,则认为是False Positive(FP)。当对应同一个真值有多个预测结果时,只有最高置信度分数的预测结果被认为是True Positive,其余被认为是False Positive。 Precision和Recall的概念如下图所示: Precision表示TP与预测边界框数量的比值 Recall表示TP与真实边界框数量的比值 改变不同的置信度阈值,可以获得多组Precision和Recall,Recall放X轴,Precision放Y轴,可以画出一个Precision-Recall曲线,简称P-R
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值