C++, C, NDK

1.干货】火爆全网的《超全C精品教程-面向对象》类(成员函数,

2023-03-07  本文已影响0人  鹏城十八少

大纲: 

1. 类函数

2. 构造函数, 析构函数, 拷贝函数 

3.友元函数

4. 静态变量

5. this指针

--------------------------------------------------

1. 类和对象

类只是一种复杂数据类型的声明,不占用内存空间。而对象是类这种数据类型的一个变量

类只是一张图纸,起到说明的作用,不占用内存空间;对象才是具体的零件,要有地方来存放,才会占用内存空间

类和结构体的区别: 类里面可以放函数! 

2. 类的创建方式

new 关键字,new出来的是指针, 指针操作,通过箭头—>, 指针不能用.对象才能用.

c++中,创建对象,是否要用new

有2种创建对象的方式! 

可以不申请new, 直接用吗?

是的, 不new 直接用就是在栈中, 如果new就是在堆中! 

反问: 对象岂不是没有空指针!  如果不new处理 ,不走构造函数??

可以在堆上创建也可以在栈上创建! 

很重要:  如果是栈,对象在方法执行完释放了, 容易调用析构函数, 同时变量会被释放! 会产生很大问题(严重)

4. 类成员函数 

成员函数可以声名, 成员函数也可以定义! 

成员函数可以定义在类定义内部,或者单独使用范围解析运算符 :: 来定义,在 :: 运算符之前必须使用类名

在类定义中定义的成员函数把函数声明为内联的,即便没有使用 inline 标识符

类中的函数,入参数可以是Void?

类中可以定义成员函数, 没有执行题

need-to-insert-img

构造函数也是函数, 所以成员函数定义, 包括构造函数

// 成员函数定义,包括构造函数

Line::Line( double len)

{

    cout << "Object is being created, length = " << len << endl;

    length = len;

}

类.start() 访问方法的话, 要把方法的实现改成类函数才能访问的到! 

need-to-insert-img

12. c++中::是什么意思

1).用于类成员函数

2).访问静态函数

3).用于静态变量的访问

总的来说: ::符号是用来访问函数的! 

例如:声明了一个类A,类A里声明了一个成员函数void f( ),但没有在类的声明里给出f的定义,那么在类外定义f时, 就要写成void A::f( ),表示这个f( )函数是类A的成员函数。

不用 ::的话, 即使是public也不能访问到变量 

need-to-insert-img

5. 构造函数中如何调用构造函数?

错误的写法, 构造函数不需要返回值

void Box::Box(){

}

应该是这样.和java一样

Box::Box(){

}

比如java中的自定义View

6.析构函数(只能有一个)

临终遗言:

java中的临终遗言是: finalize

析构函数(Destructor)也是一种特殊的成员函数,没有返回值,不需要程序员显式调用(程序员也没法显式调用),而是在销毁对象时自动执行

析构函数的名称与类的名称是完全相同的,只是在前面加了个波浪号(~)作为前缀,它不会返回任何值,也不能带有任何参数。析构函数有助于在跳出程序(比如关闭文件、释放内存等)前释放资源

classBox{

doublestate;

friendvoidstart(Boxbox);

public:

doublelength;

doublebreadth;

doubleheight;

voidset(doublelen,doublebre,doublehei);

doubleget();

Box();

~Box();

};

Box::~Box(){

cout<<"Box"<<"Box delete:"<<endl;

}

Box::Box(){

cout<<"Box"<<"Box create:"<<endl;

}

voidstart(Boxbox){

cout<<"start:"<<"ss:"<<endl;

}

doubleBox::get(){

returnlength*breadth*height;

}

voidBox::set(doublelen,doublebre,doublehei){

length=len;

breadth=bre;

height=hei;

}

intmain(){

Boxbox1;

box1.length=1.0;

box1.breadth=1.0;

box1.height=1.0;

box1.set(1.9,1.1,1.1);

start(box1);

cout<<"Box2 的体积:"<<box1.length<<endl;

return0;

}

结果:  析构函数执行了2次! 

为啥2次, 方法释放的时候调用??还是因为又产生了一个对象! 

应该是方法执行完, 栈被释放了. 然后就调用了析构函数! 

BoxBox create:

start:ss:

BoxBox delete:

Box2 的体积:1.9

BoxBox delete:

分析: 用到了栈, 然后传递了对象!!

正确写法: 不要java那种写法, 应该传递地址! 

析构函数:如果有在对象内部开辟堆内存,可以在析构函数中释放内存

用 new 分配内存时会调用构造函数,用 delete 释放内存时会调用析构函数()

new 创建的对象位于堆区,通过 delete 删除时才会调用析构函数;如果没有 delete,析构函数就不会被执行。

如果是 new 的对象,则必须调用 delete 才会调用到析构函数, 如果用了c的free会怎么样?

malloc/free 他们是一套, new/delete 它们是一套

malloc/free 不会去调用构造函数和析构函数

new/delete 会调用构造函数和析构函数

7.  拷贝构造函数 (很重要,会和析构函数相结合)

拷贝构造函数和构造函数哪个先执行?

调用构造函数调用拷贝构造函数并为指针 ptr 分配内存

一个对象给另外一个对象赋值: 

Person person1={}

Person person2=person1;

赋值,是把所有的属性赋值了! 原理: 调用了拷贝构造函数! 

 这个拷贝是浅拷贝,拷贝的是值

使用场景: 

1. 作为参数返回的时候会调用拷贝构造函数

2. 作为参数传递的时候会调用拷贝构造函数!

3. 一般要重写拷贝构造函数, 防止2次析构导致异常(释放)

classLine

{

public:

intgetLength(void);

Line(intlen);// 简单的构造函数

Line(constLine&obj);// 拷贝构造函数

~Line();

3.属性私有,公有--------->想到有友元函数! 

关键字:privite和 public

默认情况下,类的所有成员都是私有的

8. 友元函数---->为了访问类的私有函数或者属性 (我么是朋友, 我可以访问你)

友元函数是不能用类::freind

类的友元函数是定义在类外部,但有权访问类的所有私有(private)成员和保护(protected)成员。尽管友元函数的原型有在类的定义中出现过,但是友元函数并不是成员函数。

友元可以是一个函数,该函数被称为友元函数;友元也可以是一个类,该类被称为友元类,在这种情况下,整个类及其所有成员都是友元。

如果要声明函数为一个类的友元,需要在类定义中该函数原型前使用关键字 friend

注意: 1. 友元函数定义在类里面声明, 不要在函数的实现里面定义! 

2. 友元函数的作用,是让你可以通过方法访问类的私有属性,而不是方法方法私有性!

/* 因为 printWidth() 是 Box 的友元,它可以直接访问该类的任何成员 */

所以定义的时候,这样定义

friend void start(Box box);

need-to-insert-img

6.1 友元函数与普通函数的区别

友元函数:直接方法名调用。

普通函数:需要对象名::+方法名 调用

友元类是: 一个类里面放另一个类的定义! 哪个类定义了友元,服务于他本身! 

#include<iostream>

usingnamespacestd;

classCCar;//提前声明CCar类,以便后面的CDriver类使用

classCDriver

{

public:

voidModifyCar(CCar*pCar);//改装汽车

};

classCCar

{

private:

intprice;

friendintMostExpensiveCar(CCarcars[],inttotal);//声明友元

friendvoidCDriver::ModifyCar(CCar*pCar);//声明友元

};

voidCDriver::ModifyCar(CCar*pCar)

{

pCar->price+=1000;//汽车改装后价值增加

}

intMostExpensiveCar(CCarcars[],inttotal)//求最贵气车的价格

{

inttmpMax=-1;

for(inti=0;i<total;++i)

if(cars[i].price>tmpMax)

tmpMax=cars[i].price;

returntmpMax;

}

intmain()

{

return0;

}

9. 静态变量和静态函数

c++没有静态类, 但是有静态变量和静态方法! 

内存中位置: 栈? 堆? 常量池?

它在常量池中, 不在栈, 也不在堆中! 

静态属性在c++中必须要出时候,初始化必须这么写, 静态成员变量必须初始化,而且只能在类体外进行! 否则报错,如下

need-to-insert-img

   static int objectCount;

定义初始化这么定义: 

int Box::objectCount=10;

而不是这样;

  static int objectCount=10;

可是有时候我们希望在多个对象之间共享数据,对象 a 改变了某份数据后对象 b 可以检测到。

共享数据的典型使用场景是计数,以前面的 Student 类为例,如果我们想知道班级中共有多少名学生,就可以设置一份共享的变量,每次创建对象时让该变量加 1

我们可以使用静态成员变量来实现多个对象共享数据的目标。

运算符 :: 来重新声明静态变量从而对它进行初始化

类的静态成员变量为什么必须得在类外初始化?

我的理解: 由于静态变量在编译期间必须初始化,全局变量的静态或者非静态的变量都可以赋初值0。而类中的变量要用构造函数来初始化,但是在编译期间没有创造对象,所以就没有运行构造方法。故在编译期间没有给类的静态变量初始化。所以要在类外 main之前要给该静态变量初始化,不管该静态变量的作用域为private还是public,因为编译期间private没有影响。但是一旦进入运行时,就不可以调用类中的private变量。

static int objectCount;

cout << "Total objects: " << Box::objectCount << endl;

2. static 关键字

总结:

静态的属性定义时**必须要初始化** (实现) int Student::tag = 12;

静态 可以直接用类名去操作 :: Student::tag += 12;

静态的方法只能去操作静态的属性或者方法

10.自带this指针

this 是 const 指针,原因: 他是共享的, 它的值是不能被修改的. 

在 C++ 中,每一个对象都能通过 this 指针来访问自己的地址。this 指针是所有成员函数的隐含参数。因此,在成员函数内部,它可以用来指向调用对象。

不用this, 在类的内部, 也可以访问里面的变量和访问,那么为什么还要this?

和java一样, 为了防止全局变量名和局部变量名! 

友元函数没有 this 指针,因为友元不是类的成员。只有成员函数才有 this 指针。

有指针, 指针访问变量或者函数可以通过 -->的方式! 

需要对 C 结构有基本的了解,并懂得如何使用箭头 -> 运算符来访问结构成员。

cout << "月: "<< 1 + ltm->tm_mon<< endl;

void func()  {    

    static int val;

}

中,变量 val 的内存地址位于: 

A. 已初始化数据段

B.未初始化数据段     

C.堆

D.栈 

【标准答案】B

11. 要定义.h文件,原因是!

12. 对象大小

上一篇下一篇

猜你喜欢

热点阅读