登录 立即注册
金钱:

Code4App-iOS开发-iOS 开源代码库-iOS代码实例搜索-iOS特效示例-iOS代码例子下载-Code4App.com

查看: 129|回复: 6

iOS 开发者应该掌握些 C++ 知识,ios开发者平台

[复制链接]

264

主题

510

帖子

2219

金钱

手工艺人

发表于 2018-2-24 12:20:34 | 显示全部楼层 |阅读模式

                    

        作为一名 iOS 开发者,最近由于开发音频播放器需要一些 C++ 的知识,便开始学习 C++ 知识。看完2本C++的书后,对它有一些了解,这里分享给有需要的同学,如果写的有不妥的地方,还望指出。后续会利用学到的C++知识对 FreeStreamer 这个音频播放器写一篇分析其实现原理的文章。本文主要围绕 FreeStreamer 这个库用到的 C++ 语法来讲解。

        iOS 开发当中,偶尔会使用到 C++ 的知识,然而大多数同学每遇到这个问题时,选择逃避。如果从头开始学习C++语法,会花费很多时间,如同笔者一样,花费很多时间了解基础的知识。

        Objective-C 和 C++ 都是基于 C 语言而设计的,它们都具有面向对象的能力。在学习 C++ 知识之前,我们先了解下 Objective-C++,它可以把 C++ 和 Objective-C 结合起来使用,如果把两门语言的优点结合起来使用是不是会更好?腾讯开源的数据库 WCDB 是一个很好的例子,它不仅有 C++ 而且还有 Objective-C++。

        本文主要内容:

        

        类(Class)的定义与使用

        

        命名空间

        

        内存管理

        

        继承

        

        构造函数和析构函数

        

        virtual 关键字

        

        静态成员与静态函数

        

        运算符重载

        

        打印日志

        

        实例

        类(Class)

        类在面向对象中非常重要,在 Objective-C 中,所有的 Class 必需继承自 NSObject 类,当创建一个类的时候,它会包含一个 .h 和 一个 .m 文件,我们以定义一个 Person 类为例:

[Java] 查看源文件 复制代码
/* Person.h*/
#import
#interface Person:NSObject
#end
/* Person.m*/
#import"Person.h"
#implementation Person
#end

        而 C++ 中,创建一个类也会有一个头文件 Person.hpp 和实现文件 Person.cpp 。

[Java] 查看源文件 复制代码
/* Person.hpp*/
#include
class Person{

};
/* Person.cpp*/
#include"Person.hpp"

        从上面的例子我们可以看到,OC 和 C++ 定义类主要有以下不同:

        

        在实现文件中,C++ 中没有 #implementation Person #end;

        

        OC 中每个类需要继承自 NSObject;

        

        C++ 中使用 #include 导入其它文件中的代码,而 OC 使用 #import 导入其它文件代码,使用 #import 保证每个文件中不会重复导入,而使用 #include 需要开发者保证不要重复导入。

[Java] 查看源文件 复制代码
class Person{
public:
intage;
boolisChild();
private:
floatheight;
boolisNomalHeight();
};

        Person 类中定义了一个公有的成员变量 age 和 一个成员函数 isChild。一个私有的成员变量 height 和一个成员函数 isNomalHeight 。在 C++ 中可以定义某个变量或函数的作用范围,如果使用时超出作用范围编译器将会报错。而在 OC 中既使在 .h 文件中没有定义某个函数,我们任然可以调用,所以在 OC 中经常会出现以 _ 或某个前缀开头的私有函数。

        Person 类的实现:

[Java] 查看源文件 复制代码
bool Person::isChild(){
returnage>=18;
}
bool Person::isNomalHeight(){
returnheight>=170;
}

        其中 :: 表示 isChild 函数属于 Person 类,它告诉编译器从哪里找到函数 isChild。

        定义了一个 Person 类,使用的时候和 OC 会有一些不同。

        OC中只能创建堆上的对象

[Java] 查看源文件 复制代码
Person*aPerson=[[Personalloc]init];
aPerson.age=18;

        在栈上创建一个 Person

[Java] 查看源文件 复制代码
PersonaPerson;
aPerson.age=18;
NSLog(#"age==%#",#(aPerson.age));
2018-02-1912:12:20.252108+0800C++Demo[2480:84138]age==18

        在堆上创建一个 Person

[Java] 查看源文件 复制代码
Person*aPerson=new Person();
aPerson->age=18;
NSLog(#"aPersonage==%#",#(aPerson->age));
deleteaPerson;
2018-02-1912:16:25.432998+0800C++Demo[2525:88221]aPersonage==18

        命名空间

        在 C++ 中有命名空间的概念,可以帮助开发者在开发新的软件组件时不会与已有的软件组件产生命名冲突,而在 OC 中却没有命名空间的概念,我们常以前缀来与第三方库区分。它的定义为:

[Java] 查看源文件 复制代码
namespace命名空间的名字{}

        我们将上面定义的类加上命名空间:

[Java] 查看源文件 复制代码
namespaceLefex{
class Person{
public:
intage;
boolisChild();
private:
floatheight;
boolisNomalHeight();
};
}
namespaceLefex{
bool Person::isChild(){
returnage>=18;
}

bool Person::isNomalHeight(){
returnheight>=170;
}
}

        那么使用时必须加上命名空间:

[Java] 查看源文件 复制代码
Lefex:: PersonaPerson;
aPerson.age=18;
NSLog(#"age==%#",#(aPerson.age));

        内存管理

        在 OC 中使用引用计数来管理内存,当引用计数为 0 时,内存空间将被释放。而 C++ 中需要开发者自己管理内存。理解 C++ 的内存管理,我们有必要先了解一下栈内存和堆内存。

        

        栈内存:它分配的大小是固定的,当一个函数执行时,将为某些变量分配存储空间,当函数执行完成后将释放其对应的存储空间。

        

        堆内存:它会随着应用的运行,使用的空间逐步增加,分配的存储空间需要开发者自己释放。

[Java] 查看源文件 复制代码
void Person::ageMemory(){
intstackAge=20;

int*heapAge=(int*)malloc(sizeof(int));
*heapAge=20;
free(heapAge);
}

        stackAge 为栈内存,不需要开发者自己释放内存,当 ageMemory 函数执行完成后 stackAge 将被释放。heapAge 为堆空间,当函数 ageMemory 执行完成后,它不会释放,需要开发者手动释放。

        下面这个例子是创建了一个 Person 对象,它使用的是堆内存,需要使用 delete 释放其内存空间。这里需要注意访问堆对象时使用 -> 访问它的成员或者方法,而访问栈对象时使用 . 访问它的成员或者方法。

        在 OC 中,当一个对象为 nil 时调用一个方法时 [nil doSomeThing] , 程序并不会执行 doSomeThing 方法,而在 C++ 中,NULL-> doSomeThing ,程序将 crash。

[Java] 查看源文件 复制代码
Lefex:: Person*aPerson=newLefex:: Person();
aPerson->age=18;
NSLog(#"age==%#",#(aPerson->age));
NSLog(#"isachild:%#",#(aPerson->isChild()));
deleteaPerson;

        继承

        C++ 中支持多继承,也就是说一个类可以继承多个类。而在 OC 中只能使用单继承。与 OC 中不同的一点就是增加了修饰符(比如:public),这样用来限制继承的属性和方法的范围。

[Java] 查看源文件 复制代码
//男人
classMan:publicLefex:: Person{

};
//女人
classWoman:publicLefex:: Person{

};
//人妖
classFreak:publicMan,publicWoman{
};

        构造函数和析构函数

        构造函数通常在 OC 中使用的是 init,而在 C++ 中默认的构造函数是于类名相同的函数。比如类 Person 的默认构造函数是 Person(),自定义一个构造函数 Person(int age, int height) 。在 OC 中析构函数如 dealloc,而在 C++ 中是函数 ~Person(),当一个类被释放后,析构函数会自动执行。

[Java] 查看源文件 复制代码
//默认构造函数
Person:: Person(){
printf("Initperson");
}
//初始化列表构造函数
Person:: Person()
:age(0),
height(0),
m_delegate(0){
printf("Initperson\n");
}
//自定义构造函数
Person:: Person(intage,intheight){
this->age=age;
this->height=height;
}

//析构函数
Person::~Person(){
printf("Deallocperson");
}

        虚析构函数:为了保证析构函数可以正常的被执行,引入了虚析构函数,一般基类中的析构函数都是虚析构函数。定义方式如下。

[Java] 查看源文件 复制代码
virtual~Person();
Person::~Person(){
printf("persondealloccalled\n");
}

        virtual 关键字

        虚函数是一种非静态的成员函数,定义格式:

[Java] 查看源文件 复制代码
virtual{函数体}

        纯虚函数:是一种特殊的虚函数,这是一种没有具体实现的虚函数,定义格式:

[Java] 查看源文件 复制代码
virtual()=0;

        抽象类:它是一个不能有实例的类,这样的类唯一用途在于被继承。一个抽象类中至少具有一个虚函数,它主要的作用来组织一个继承的层次结构,并由它提供一个公共的根。

        有了抽象类和纯虚函数,就可以实现类似于 OC 中的 delegate。

[Java] 查看源文件 复制代码
//相当于OC中的代理
class Person_delegate{
public:
//=0表示无实现
virtualvoidageDidChange()=0;
};
//继承了 Person_delegate,Woman类真正实现了 Person_delegate的纯虚函数
classWoman:publicLefex:: Person,publicLefex:: Person_delegate{
public:
Woman();
voidageDidChange();
};

        综上可以看到它于 OC 中实现的思路一致。

        静态成员与静态函数

        静态成员使用 static 修饰,只对其进行一次赋值,将一直保留这个值,直到下次被修改。

        在 Person 类中定义一个静态变量 weight。

[Java] 查看源文件 复制代码
staticintweight;

        使用时直接:Person::weight; 即可访问静态变量。

        静态成员函数与静态成员的定义一致。

[Java] 查看源文件 复制代码
staticfloatcurrentWeight();

        需要注意的是,在静态成员函数中,不可以使用非静态成员。

        调用:

[Java] 查看源文件 复制代码
Person::currentWeight();
也可以:
aPerson->currentWeight();

        运算符重载

        有时候利用系统的运算符作自定义对象之间的比较的时候,不得不对运算符进行重载。

        定义:

[Java] 查看源文件 复制代码
类型operatorop(参数列表){}

        “类型”为函数的返回类型,函数名是 “operator op”,由关键字 operator 和被重载的运算符op组成。“参数列表”列出该运算符所需要的操作数。

        例子:

[Java] 查看源文件 复制代码
// Person类中定义 Person是否相等。
booloperator==(Person&){
if(this->age==person.age){
returntrue;
}
returnfalse;
};
[Java] 查看源文件 复制代码
+(void)operatorOverload
{
Lefex:: PersonaPerson;
aPerson.age=18;

Lefex:: PersonaPerson2;
aPerson2.age=18;

if(aPerson==aPerson2){
NSLog(#"aPersonisequaltoaPerson2");
}else{
NSLog(#"aPersonisnotequaltoaPerson2");
}
}

        打印日志

        C++ 中打印日志需要导入库 #include 。

        

        \n 和 endl 效果一样都是换行;

        

        打印多个使用

289

主题

510

帖子

2401

金钱

手工艺人

发表于 2018-2-24 12:23:11 | 显示全部楼层
我是来学习的

169

主题

391

帖子

1010

金钱

手工艺人

发表于 2018-2-24 12:25:40 | 显示全部楼层
虽不明,但觉厉...

0

主题

7048

帖子

-519

金钱

限制会员

发表于 2018-2-24 12:29:38 | 显示全部楼层
支持,感谢,祝code4app越来越好~

14

主题

7049

帖子

1413

金钱

手工艺人

发表于 2018-2-24 12:30:45 | 显示全部楼层
感谢分享,code4app有你更精彩

320

主题

555

帖子

2421

金钱

手工艺人

发表于 2018-2-24 12:34:01 | 显示全部楼层
感谢大神~

285

主题

511

帖子

467

金钱

手工艺人

发表于 2018-2-24 12:36:27 | 显示全部楼层
感谢大神分享,必须顶!
*滑动验证:
您需要登录后才可以回帖 登录 | 立即注册 新浪微博登陆

本版积分规则

关闭

每日头条

通过邮件订阅最新 Code4App 信息
上一条 /4 下一条

广告投放| Github|申请友链|手机版|Code4App ( 粤ICP备15117877号-1 )

快速回复 返回顶部 返回列表