《C++程序设计》笔记之-基于对象程序设计

面向对象:除主函数被操作系统调用外,其它函数可以相互调用,面向一个个函数。       程序 = 数据结构 + 算法

基于对象:以类为基本单位构成的程序

面向对象:抽象、封装、继承、多态            对象 = 数据结构 + 算法    程序 = (对象 + 对象 + 。。。)+消息

 

如果类中定义既不指定private,也不指定public,默认为private  ,

protected:不能被类外(即类体,类的对象属于类外)访问,但能被派生类成员函数访问

 

定义:可以不出现类名,直接定义,合法,但少用(类的申明和使用分开,并不只为一个程序服务,一般放在类库中)

class

{

。。。

}stu1,stu2;

 

成员函数:一般定义为public,为类的对外接口。成员函数可以访问类中所有成员(public的和private的.)

类体定义应在函数定义之前,否则编译出错。

        内置成员函数(内置函数):一般规模较小,调用频率高,程序调用它时并不真正执行函数调用过程(如保留返回地址等处理),而是把函数代码嵌入程序调用点,大大减小调用成员函数时间开销。  用  inline 申明(类体内定义成员函数可省略inline,默认为内置的)

         若在类体外定义inline函数,则应将它与类体放在同一源文件中,否则编译无法进行置换(将函数代码拷贝到函数调用点)

        缺点:不利于类的接口与类的实现分离,不利于信息隐蔽,

       

        成员函数存储方式:每个对象所占用的存储空间只是改对象数据成员所占存储空间,各对象公用一段成员函数代码(包括inline函数),用this指针区分(也共用一份静态数据成员)

        类外不能访问私有成员,如stu1.num = 1010;  (若num申明为private,则此复制语句错误)

类的申明和实现(成员函数定义)放在不同文件中,这样成员函数只需编译一次,将形成的目标文件保存起来,需要时再与程序目标文件连接(类似于库函数)

C++程序员不习惯将所有申明写在开头,有别于C语言

对象初始化:

若一个类的所有成员都是public的,则在定义对象时可以进行初始化。(此时与结构体初始化类似)

用构造函数初始化:(不需用户调用,建立对象时自动执行)。名字与类名相同,无类型(不是void型),不返回任何值,一般为public,只能执行一次

用一个类对象初始化另一个类对象  

Time t1 = t2,  把t2各数据成员值复制到t1对应成员,而不调用t1的构造函数

带参数的构造函数:Box::Box(int h, int  w, int len )

   {

......

   }

或参数初始化表: Box(int h, int w, int len):height(h),width(w),length(len){ }           //后面无分号

若数据成员为数组,则必须在构造函数体内对其赋值,而不能在参数初始化表内对其初始化

Student(int n,char s, char nam[]):num(n),sex(s){strcpy(name,nam);}

构造函数重载:具有相同名字,参数个数或类型不同

无参构造函数属于默认构造函数,一个类只有一个

使用默认参数的构造函数:     Box(int h =10, int w = 10, int len =10);   //类体内申明,指定默认参数

   Box::Box(int h, int  w, int len )          //类体外定义

                   {

           ......

                  }         //此时即使定义对象时实参不全或没有,也会使用默认值

一般不应同时使用构造函数重载和有默认参数的构造函数,很容易冲突


析构函数:并不是删除对象,而是在撤销对象占用内存前执行一些清理工作。

1、自动局部对象:当函数调用结束时对象释放,释放前自动执行析构函数

2、static局部对象:函数结束时对象不释放,等到main函数结束或调用exit结束程序时,调用static对象析构函数

3、全局对象:程序离开其作用域时(如main函数结束)调用其析构函数

由于析构函数没有类型,没有参数,所以不能重载,一个类只有一个析构函数

调用析构函数顺序:一般与调用构造函数顺序相反(相当于栈)(对同一类存储类别对象而言的,static或者自动的)


对象数组: Box a[3] = 

{

Box(1,2,3),

Box(4,5,6),

Box(7,8,9),

};


指向对象成员函数的指针:  以下3点必须匹配:1、函数参数类型和参数个数 2、函数返回值 3、所属的类

void (Time::*p)();             //和C语言相比多了类名,即第三条约束

p = &Time::get_time;             此时p指向public成员函数get_time的入口地址     get_time不需要参数,只是函数名


This指针,隐式调用

对象调用函数 Box1.volume();               

相当于:     Box1.volume(&volume);



公用数据对象的保护:

常对象:必须要有初值,所有数据成员值不能修改               Time const t1(1,2,3); 或者const Time t1(1,2,3);

常对象只能调用其常成员函数(除系统自动调用的隐式的构造函数和析构函数)即常成员函数是其唯一对外接口

常成员函数只能访问常对象数据成员,不能修改。但若将数据成员申明为mutable,就可以用常成员函数修改

对于一般的类:

常成员函数只能引用本类中的数据成员,不能修改。

申明:void get_time()const;    //const在后,   申明和定义时都要加const,调用时不必加

非const成员函数可以访问const数据成员,但常对象不能调用非const成员函数


对象的动态建立和释放:

静态定义的对象,在程序运行过程中,对象所占空间不能释放,直到函数结束

动态建立对象:需要时建立,不需要时随时撤销,提高内存利用率

用new建立的对象一般不用对象名,用指针访问

Box *p = new Box(1,2,3,);     返回对象在内存中的首地址

对象的赋值: 类的数据成员中不能包括动态分配的数据,否则在赋值时出现严重后果

原因:如果某个类的对象a里面有动态申请的数据,当你把a直接复制给同一个类的对象b的时候,a中的动态指针也给了b,这样a,b中的指针指向同一块内存.这样无论a或者b释放内存都会导致另外一个访内违例崩溃.

解决这个问题需要自己重载赋值运算符和拷贝构造函数.如果不想重载,并且也不喜欢出现错误,那么就把这两类函数声明为私有。
对象的复制:Box Box2(Box1);用已有的类Box1克隆出Box2
	在建立对象时调用一个特殊构造函数:复制(拷贝)构造函数,其只有一个参数,为本类对象,
	Box::Box(const Box &b)
	{
		height = b.heigt;   width = b.width;  length = b.len;
	}
 
静态数据成员:在同类多个对象间实现共享,在内存中只占用一份空间
	即使不定义对象,也为静态数据成员分配空间,能被引用(通过类名) Box::height
	不随对象撤销而释放,程序结束时才释放空间
	可以初始化,但只能在类体外:默认为0
							int Box::heigth = 10;
	不能用参数初始化表对静态成员初始化。
 
静态成员函数:不是为了对象之间的沟通,而是为了处理静态数据成员
			静态成员函数不属于哪个对象,没有this指针,无法对某个对象中的非静态数据成员访问
			公用成员函数对本对象中的静态和非静态数据成员都能访问
 
友元函数:可以访问本类私有成员
		Date类体里申明:   	friend void display(Date &);
						 friend void Time::display(Date &);
友元类:里面所有函数都是其友元函数          友元关系为单向,且不能传递
		友元类不利于信息屏蔽,一般不把一个类申明为友元类,但有利于数据共享   (两者中选择平衡点)
 
类模板:
	template <class numtype>   //numtype为虚拟类型名,一般为一个数据类型
	类模板包括类型参数(参数化的类)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值