C++,一些常用的知识点
用typedef定义数组、指针、结构等类型将带来很大的方便,不仅使程序书写简单而且使意义更为明确,因而增强了可读 性。 C++中是用关键字typedef定义一个标识符来代表一种数据类型,该标识符可以象其它基本类型的标识符一样使用。在用typedef进行类型定 义时,其语法和变量定义很相似。typedef定义的一般形式为:
typedef 原类型名 新类型名
例如:
typedef int * intptr;
定义intptr为一个指向整型的指针类型。变量定义语句:
intptr p;
等价于:
int * p;
需要 注意 的是:typedef定义的类型只是C++已有类型的别名,而不是新类型。有时也可用宏定义来代替typedef的功能,但是宏定义是由预处理完成的,而typedef则是在编译时完成的,后者更为灵活方便。
2
namespace的使用
有名的命名空间:
namespace 命名空间名 {
声明序列可选
}
无名的命名空间:
namespace {
声明序列可选
}
-------------------------------------------------
命名空间的成员,是在命名空间定义中的花括号内声明了名称。可以在命名空间的定义内,定义命名空间 的成员(内部定义)。也可以只在命名空间的定义内声明成员,而在命名空间的定义之外,定义命名空间的成员(外部定义)。
命名空间成员的外部定义的格式为:
命名空间名::成员名 ……
例如:
// out.h
namespace Outer { // 命名空间Outer的定义
int i; // 命名空间Outer的成员i的内部定义
namespace Inner { // 子命名空间Inner的内部定义
void f() { i++; } // 命名空间Inner的成员f()的内部定义,其中的i为Outer::i
int i;
void g() { i++; } // 命名空间Inner的成员g()的内部定义,其中的i为Inner::i
void h(); // 命名空间Inner的成员h()的声明
}
void f(); // 命名空间Outer的成员f()的声明
// namespace Inner2; // 错误,不能声明子命名空间
}
void Outer::f() {i--;} // 命名空间Outer的成员f()的外部定义
void Outer::Inner::h() {i--;} // 命名空间Inner的成员h()的外部定义
// namespace Outer::Inner2 {} // 错误,不能在外部定义子命名空间
注意:
不能在命名空间的定义中声明(另一个嵌套的)子命名空间,只能在命名空间的定义中定义子命名空间。
也不能直接使用“命名空间名::成员名 ……”定义方式,为命名空间添加新成员,而必须先在命名空间的定义中添加新成员的声明。另外,命名空间是开放的,即可以随时把新的成员名称加入到已有的命 名空间之中去。方法是,多次声明和 定义同一命名空间,每次添加自己的新成员和名称。例如:
namespace A {
int i;搞怪小四
void f();
} // 现在A有成员i和f()
namespace A {
int j;
void g();
} // 现在A有成员i、f()、j和g()
还可以用多种方法,来组合现有的命名空间,让它们为我所用。例如:
namespace My_lib {
using namespace His_string;
using namespace Her_vector;
using Your_list::List;
void my_f(String &, List &);
}
……
using namespace My_lib;
……
Vector<String> vs[5];
List<int> li[10];
1
my_f(vs[2], li[5]);
1
使用命名空间
作用域解析运算符(::)
3
1)虚函数和纯虚函数
(1). 虚函数和纯虚函数可以定义在同一个类(class)中,含有纯虚函数的类被称为抽象类(abstract class),而只含有虚函数的类(class)不能被称为抽象类(abstract class)。
( 2). 虚函数可以被直接使用,也可以被子类(sub class)重载以后以多态的形式调用,而纯虚函数必须在子类(sub class)中实现该函数才可以使用,因为纯虚函数在基类(base class)
只有声明而没有定义。
(3). 虚函数和纯虚函数都可以在子类(sub class)中被重载,以多态的形式被调用。
( 4). 虚函数和纯虚函数通常存在于抽象基类(abstract base class -ABC)之中,被继承的子类重载,目的是提供一个统一的接口。
(5). 虚函数的定义形式:virtual {method body}
纯虚函数的定义形式:virtual { } = 0;
在虚函数和纯虚函数的定义中不能有static标识符,原因很简单,被static修饰的函数在编译时候要求前期bind,然而虚函数却是动态绑定(run-time bind),而且被两者修饰的函数生命周期(life recycle)也不一样。
(6). 如果一个类中含有纯虚函数,那么任何试图对该类进行实例化的语句都将导致错误的产生,因为抽象基类(ABC)是不能被直接调用的。必须被子类继承重载以后,根据要求调用其子类的方法。
纯虚函数和虚函数的区别在于前者不包含定义,而后者包含函数体。
2)抽象类:
抽象类是一种特殊的类,它是为了抽象和设计的目的为建立的,它处于继承层次结构的较上层。
⑴抽象类的定义:
称带有纯虚函数的类为抽象类。
⑵抽象类的作用:
抽象类的主要作用是将有关的操作作为结果接口组织在一个继承层次结构中,由它来为派生类提供一个公共的根,派生类将具体实现在其基类中作为接口的操作。所以派生类实际上刻画了一组子类的操作接口的通用语义,这些语义也传给子类,子类可以具体实现这些语义,也可以再将这些语义传给自己的子类。
(3)使用抽象类时注意:
? 抽象类只能作为基类来使用,其纯虚函数的实现由派生类给出。如果派生类中没有重新定义纯虚函数,而只是继承基类的纯虚函数,则这个派生类仍然还是一个抽象类。如果派生类中给出了基类纯虚函数的实现,则该派生类就不再是抽象类了,它是一个可以建立对象的具体的类。
? 抽象类是不能定义对象的。
4.
调用操作符重载:我们可以为类类型的对象重载调用操作符即小括弧”()“,定义了调用操作符的类,在使用定义的调用操作符时,行为就像是调用函数,所以这种对象称为函数对象,即行为类似函数的对象:
如下例子为类A定义了调用操作符,功能是返回一个绝对值:
class A
{
public:
int operator() (int val)
{
return val < 0 ? -val : val;
}
};
调用操作符使用以下两种方法都可以:
A a;
int n = a.operator()(-1);
int n = a(-1); //使用方式像是调用了一个函数
调用操作符可以重载多个版本,通过函数形参的类型及数目区分,如再为类A重载一个形参类型为char *的调用操作符函数:
void operator(char *p)
{
*p = '\0';
}
使用以上调用操作符:
char arr[] = "ABC";
char *pa = arr;
a.operator()(pa);
a(pa);
二:函数对象用于标准库算法:
a:例如查找比指定值大的数,可以先定义一个类B,为其定义调用操作符,使用该类的对象实现查找:
class B
{
public:
B(int val = 0) : ival(val) {} //构造函数初始化成员 ival;
bool operator()(const int &v)
{
return v > ival; //返回真值,如果传递进来的实参大于成员ival,ival在调用构造函数时被初始化;
}
private:
int ival;
};
用标准库算法find_if进行查找,比如查找大于10的数:
int b[] = {1, 52, 12, 30, 9, 19};
vector<int> ivec(b, b+6);
vector<int>::iterator ite = ivec.begin();
while((ite = find_if(ite, ivec.end(), B(10))) != ivec.end())
{
cout << *ite << " ";
ite++;
}
find_if函数的第三个参数是一个接受一个参数并返回bool型的函数,在这里我们可以传递给find_if算法函数一个类类型B的临时对象,通过传
递值10给构造函数初始成员ival,现在find_if每次调用它的函数形参时,依次将vector中的每个元素都应用类B的调用操作符,然后该操作符
根据成员ival的值,对传进的实参即vector的每个元素进行比较,如果函数对象返回为真,则find_if返回指向该元素的迭代器;
b:统计大于指定值的次数,以上述代码为基础:
int n = count_if(ivec.begin(), ivec.end(), B(10));
同样,count_if以函数调用的方式调用类B调用操作符,对vector中每个元素进行比较,如果为真,则计数器加1,知道vector的末端元素;
全部代码:
- #include <iostream>
- #include <vector>
- #include <algorithm>
- using namespace std;
- class A
- {
- public:
- int operator() (int val)
- {
- return val > 0 ? val : -val;
- }
- void operator() (char *p)
- {
- *p = 'B';
- }
- };
- class B
- {
- public:
- B(int val = 0) : ival(val) {} //构造函数初始化成员 ival;
- bool operator()(const int &v)
- {
- return v > ival; //返回真值,如果传递进来的实参大于成员ival,ival在调用构造函数时被初始化;
- }
- private:
- int ival;
- };
- int main()
- {
- int i = -42;
- A a;
- unsigned int ui = a(i);
- // unsigned int ui = a.operator()(i);
- cout << ui << endl;
- char arr[] = "ABC";
- char *pa = arr;
- a(pa);
- //a.operator()(pa);
- cout << pa << endl;
- int b[] = {1, 52, 12, 30, 9, 19};
- vector<int> ivec(b, b+6);
- vector<int>::iterator ite = ivec.begin();
- while((ite = find_if(ite, ivec.end(), B(10))) != ivec.end())
- {
- cout << *ite << " ";
- ite++;
- }
- cout << endl;
- int n = count_if(ivec.begin(), ivec.end(), B(10));
- cout << "n:" << n << endl;
- return 0;
- }
运行结果:
42
BBC
52 12 30 19
n:4
上述代码g++编译通过!
函数调用操作符是(),因此,此操作符的函数重载是operator()()。重载函数调用操作符的类对象称为函数对象或仿函数(functor),因为我们可以像使用函数名一样使用对象名。先来看一个简单的例子。下面是重载了函数调用操作符的一个类:
- class Area
- {
- public:
- int operator()(int length, int width) { return length*width; }
- };
此类中的操作符函数计算一个面积,它是两个整数实参的乘积。为了使用此操作符函数,只需要创建一个类型为Area的对象,例如:
- Area area; // Create function object
- int pitchLength(100), pitchWidth(50);
- int pitchArea = area(pitchLength, pitchWidth); // Execute function call overload
第一条语句创建第三条语句中使用的area对象,第三条语句使用此对象来调用对象的函数调用操作符。在此例中,返回的是足球场的面积。
当然,也可以将一个函数对象传递给另一个函数,就像传递任何其他对象一样。看看下面这个函数:
- void printArea(int length, int width, Area& area)
- {
- cout << "Area is " << area(length, width);
- }
下面是使用此函数的语句:
- printArea(20, 35, Area());
这条语句调用printArea()函数,前两个实参分别指定矩形的长和宽。第三个实参调用默认构造函数,以创建一个Area对象,函数中计算面积 时要使用此Area对象。因此,函数对象提供了一种方式,可以将函数作为实参传递给另一个函数。与使用函数指针相比,这种方式既简单又容易。
注意:第10章将学习std::function<>模板,它为传递函数提供了更大的灵活性。
C++,一些常用的知识点的更多相关文章
- JS中常用开发知识点
JS中常用开发知识点 1.获取指定范围内的随机数 2.随机获取数组中的元素 3.生成从0到指定值的数字数组 等同于: 4.打乱数字数组的顺序 5.对象转换为数组 //注意对象必须是以下格式的才可以通 ...
- php 常用的知识点归集(下)
24.静态属性与静态方法在类中的使用 需求:在玩CS的时候不停有伙伴加入,那么现在想知道共有多少人在玩,这个时候就可能用静态变量的方法来处理 利用原有的全局变量的方法来解决以上的问题 <?php ...
- Groovy常用编程知识点简明教程
概述 Groovy 是一门基于JVM的动态类型语言,可以与 Java 平台几乎无缝融合(与Java代码一样编译成字节码). 使用 Groovy ,可以增强 Java 应用的灵活性和可扩展性,提升开发效 ...
- unity常用小知识点
感觉自己抑郁变得更严重了,超级敏感,经常想崩溃大哭,睡眠超差,实在不想药物治疗,多看看书,多约约朋友,多出去走走. 来几句鸡汤吧,人一定要活得明白一点,任何关系都不要不清不楚,说不定最后受伤的就是自个 ...
- 常用ES6-ES10知识点总结
在工作中我们会常用到的一些es6-es10的一些特性还记得多少,今天就让我们重新复习一遍 ES6语法 1.Let 1.let声明的变量具有块级作用域, { let a = 1 } console.lo ...
- iOS中多线程常用的知识点
1.pThread 跨平台的多线程技术 , 是IEEE制定的POSIX 表示可移植性操作系统接口的多线程计数,UNIX内核平台 Unix,Linux,Mac(小红帽) (windows上有可移 ...
- rails 常用的知识点
按惯例先上网址: http://guides.ruby-china.org/ 适合初学者很好的文章 ===========================知识点================ ...
- java常用基础知识点 (持续追加)
作为一个Java编程人,会经常用上JDK中的大量的API类库,常用的有字符串操作.集合操作.文本操作.输入输出操作.以及网络操作, 常用的包: 1. java.lang Java程序的基础类,字符串, ...
- ifram一些常用的知识点
本文摘自:http://www.cnblogs.com/duankaige/archive/2012/09/20/2695012.html iframe的调用包括以下几个方面:(调用包含html ...
- AngularJS应用,常用数组知识点
AngularJS 1:ng-click,ng-model,ng-bind,ng-class,ng-hide,ng-app 2:placeholder, 3:{}中加入代码“:true|false”, ...
随机推荐
- mac for appium环境安装
之前写过windows 安装appium环境步骤. 1. 需求的前置条件如下 (mac 自动git.ruby.brew命令): 2. java 环境 3. git 环境 4. ruby环境 5. b ...
- 【转】Microsoft .Net Remoting之Marshal、Disconnect与生命周期以及跟踪服务
Marshal.Disconnect与生命周期以及跟踪服务 一.远程对象的激活 在Remoting中有三种激活方式,一般的实现是通过RemotingServices类的静态方法来完成.工作过程事实上是 ...
- 类的数据成员加前缀 m_(表示 member)
类的数据成员加前缀 m_(表示 member),这样可以避免数据成员与 成员函数的参数同名. 例如: void Object::SetValue(int width, int height) { m_ ...
- ubuntu 12.04 LTS server 中文乱码【转】
ubuntu 12.04 LTS server 中文乱码 最近装了一台ubuntu 12.04 server装完后是没有桌面的,后来又手动安装了桌面,但进行后发现桌面是乱码,应该是缺少字体在googl ...
- (转)音频输出PCM与LPCM有什么不同
多声道LPCM:无损音轨原始存在格式,概念上等效于wave文件,并不需要运算解码,可直接输入功放进行DA转换,光纤和同轴接口只能传输2声道LPCM,多声道LPCM需要HDMI接口传输. PCM: ...
- MVC中用View.bag保存json字符串。在js中使用,不用ajax请求。。。。
有时候我们只需要使用一次json数据,这时候直接在后台查出json,然后用view.bag传到前台使用,就会很方便..(在前台用ajax请求的话,感觉有点多余..) 上代码 后台: public Ac ...
- PHP截断函数mb_substr()
提示:mb_substr在于php中是默认不被支持的我们需要在在windows目录下找到php.ini打开编辑,搜索mbstring.dll,找到;extension=php_mbstring.dll ...
- VC++ 6.0开发套件(自己收藏!)
安装镜像ISO VC++ 6.0_SP6_Win7企业版(中英文集成).iso MSDN安装镜像ISO MSDN_Oct_200 ...
- VC++ :实现简单的文件拖放(Drag and Drop)功能
1) VC++ 6.0 新建一个基于对话框的MFC的工程,取名MfcDropFiles: 2) 去除默认的控件,包括确定/取消按钮,以及一个静态文本: 3) 在对话框空白区域拖放一个ListBox控件 ...
- ubuntu 16.04 appstreamcli 问题
http://blog.csdn.net/zhbpd/article/details/77508675