C++面向对象02【初识面向对象,类,构造、复制构造、类型转换构造、析构函数】

摘要:1.why?
2.面向对象程序设计
3.类的成员:成员变量,成员函数,可访问范围
4.使用类的成员变量和成员函数的方法
5.类成员地可访问范围
6.成员函数也可重载,也可有缺省值
7.构造函数
8.复制(拷贝)构造函数
9.类型转换构造函数
10.析构函数

1.why?
c语言中:程序=数据结构+算法
随着程序规模增加,程序逐渐难以理解,很难一下子看出来:

  • 某个数据结构到底有哪些函数可以对它进行操作
  • 某个函数到底是用来操作哪些数据结构的
  • 任何两个函数之间存在怎样的调用关系

结构化程序设计不足:没有封装和隐藏的概念,重用时抽取代码困难

2.面向对象程序设计
面向对象程序=类+类+类+……+类
设计程序的过程为设计类的过程

抽象:将特点和行为归纳出来
封装:将数据结构和操作该数据结构的函数捆绑在一起,形成一个类,使其呈现出显而易见的紧密关系
隐藏:设置私有成员的机制

基本特点:抽象,封装,继承,多态

3.类的成员:成员变量,成员函数
类:带函数的结构
对象:类定义的变量,类的实例
类的名字:用户自定义的类型的名字
对象的内存分配:和结构变量一样,等于所有成员变量的大小之和

对象之间可以用“=”进行赋值,但不能进行比较(除非那些运算符被重载)

类的成员函数和类的定义可以分开写,仅在定义中声明成员函数,内容放到类外写
例:int CRectangle::Area(){
return w*h;
}
“ CRectangle::”说明后面的函数是这个类的成员函数,不是普通函数

类成员的可访问范围
private:私有成员,只能在成员函数内访问
public:公有成员,可以在任何地方访问
protected:保护成员
PS:以上三种关键字出现次数和先后顺序都没有限制
PS:如果某个成员前无上述关键字,则缺省地被认为是私有成员

4.使用类的成员变量和成员函数的方法

  • 对象名.成员名
  • 指针->成员名
  • 引用名.成员名

5.类成员地可访问范围

  • 成员函数内部
    当前对象的全部属性、函数
    同类其它对象的全部属性、函数
    PS:成员函数以外,只能访问该类对象的公有成员

6.成员函数也可重载,也可有缺省值
注意避免重载时的二义性
例:void valuex(int val=0){}
int valuex(){}
A.valuex();//报错,有二义性计算机不知道调用哪一个函数

7.构造函数
名字与类名相同,可以有参数,不能有返回值(void也不行)
作用:对对象进行初始化(不是给对象分配空间)
如果定义类时没写构造函数,则编译器生成一个默认的无参数构造函数(不做任何操作)
对象生成时构造函数自动被调用,一旦生成,再也不能在其上执行构造函数
一个类可以有多个构造函数

例:三个构造函数
CSample (){}//(1)
CSample (int n){}//(2)
CSample (int n,int m){}//(3)

int main(){
CSample a(1);//调用(2)
CSample b[2]= {4,5};//数组中两个元素调用了两次(2)
CSample c[2]= {3};//数组中第一个元素调用(2),第二个元素调用(1)
CSample d[3]={1,CSample(1,2)};//数组中三个元素分别调用(2),(3),(1)

重要:CSample * e[3]={new CSample(4),new CSample(1,2)};//定义指针数组并不会自动调用构造函数,需要用new,所以这个数组中前两个元素分别指向由(2)初始化的new出来的对象由(3)初始化的new出来的对象,最后一个指针元素没有初始化

8.复制(拷贝)构造函数
X::X(X&) 或 X::X(const X&) //多用后者,能以常量对象作为参数
只有一个参数,即对同类对象的引用
如果没有定义复制构造函数,编译器会生成默认复制构造函数

复制构造函数起作用的三种情况

  • 用一个对象去初始化同类的另一个对象时
    Complex c2(c1);
    Complex c2=c1; //首次出现是初始化,不是赋值

  • 如果某函数有一个参数是类A的对象,那么该函数被调 用时,类A的复制构造函数将被调用
    void Func(A a1){}
    int main(){
    A a2;
    Func(a2);//自动调用复制构造函数,a1是a2的复制品
    return 0;
    调用这样的函数时,生成形参会引发复制构造函数的调用,开销大,可以考虑使用引用类型作为参数。
    如果想确保实参的值在函数中不应被改变,可加上const关键字变成常量引用。
    这样若函数中有改变实参的值的语句,编译器会报错。

  • 如果函数的返回值是类A的对象时,则函数返回时,A的复制构造函数被调用

PS:对象间的赋值并不导致**复制(拷贝)**构造函数被调用

问题:为什么要自己写复制构造函数?用编译器默认的不也能完成复制任务吗?

9.类型转换构造函数
目的:实现类型的自动转换
定义:【只有一个参数,且不是复制构造函数】的构造函数
需要的时候,编译系统会自动调用转换构造函数,建立一个无名的临时对象(或临时变量)【需要创建和消亡的】
例:Complex(int i){}//是转换构造函数
Complex(double r,double i) {} //不是

    Complex c1(7,8);//不调用转换构造函数
    Complex c2=12;//调用
     c1=9;//9被自动转换成一个临时Complex对象,再赋值给c1

10.析构函数
名字与类名相同,在前面加‘~’,没有参数和返回值,一个类最多只能有一个析构函数
对象消亡时自动被调用
可以定义析构函数在对象消亡前做善后工作(比如释放分配的空间)
如果定义类时没写析构函数,则编译器生成缺省析构函数,它什么也不做
对象数组生命期结束时,对象数组的每个元素的析构函数都会被调用
例:
class CMyclass{……
……
};
CMyclass obj;
CMyclass fun(CMyclass sobj){
return sobj;
}

int main(){
obj=fun(obj);//fun函数结束时形参sobj消亡调用一次析构函数;复制函数生成临时对象返回后,临时对象消亡调用一次析构函数
return 0;
}//程序结束,全局对象obj消亡调用一次析构函数
总共调用三次析构函数

{static Demo d1(1);
Demo d2(2);}
//大括号结束时只调用一次析构函数,因为静态局部变量在整个函数结束时才消亡

一般来说先构造的先析构

delete时调用析构函数
new出来的对象,必须用delete释放,否则即使程序结束也不会消亡不会调用析构函数

PS:Dev编译器中,系统会自动优化,函数返回一个对象时不调用复制函数生成临时对象,直接返回。
Visual Studio正常

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值