c++的类(一)

类的简述


结构体(struct):只能封装属性(数据)

类(class):将属性(数据)和行为(函数)封装在一起

类中的成员权限


class xxxx

{

public:  //公有的,类内外皆可访问

protect:  //保护的,类外不可访问,类内和子类可访问

private:  //私有的,类外和子类不可访问,类内可访问

};

利用public和private的关系

给成员变量设置为只读权限

class xxxxx

{

public:

       int ReadOnly()

      {

             return readonly;

       }

private:

      int readonly;

}

给成员变量设置为只写权限

class xxxxx

{

public:

       void WriteOnly(int value)

      {

             writeonly=value;

       }

private:

      int writeonly;

}

以上两者结合(两个函数)即可给成员变量设置为可读可写权限

类的构造和析构


构造:创建对象(类变量)时,对对象进行初始化

析构:销毁对象时,对对象进行清理释放

一般要人为提供,若不提供,编译器也会提供(不会做任何操作),两者都不需要人为调用

构造函数:

  1. 没有返回值
  2. 函数名和类名一致
  3. 有参数,可多个
  4. 可函数重载
  5. 创建对象时自动调用

析构函数:

  1. 没有返回值
  2. 函数名=~类名
  3. 没参数
  4. 不能重载
  5. 销毁对象之前自动调用

构造函数的分类:

无参构造和有参构造

普通构造和拷贝构造

拷贝构造:类名(const 类名 &obj)

  1. 若定义了拷贝构造,系统不再提供默认拷贝构造
  2. 默认的拷贝构造就是值的拷贝
  3. 创建对象时,不能调用对应的构造函数,则创建对象失败
  4. 调用时机:旧对象初始化新对象

                           形参是一个对象(非引用)

                           返回的局部对象

class Person

{

public:

       int age;

       string id;

       //构造可重载(多个)

       Person()

       {

             cout<<"无参构造"<<endl;

       }

       Person(int a, string b)

       {

               cout<<"有参构造"<<endl;

              age=a;

              id=b;

        }

        Person(const Person &p)

        {

               cout<<"拷贝构造"<<endl;

               age=p.age;

               id=p.id;

        }

};

调用构造函数的方法

void test01()

{

         //普通调用

        Person p1;  //无参构造,不能括号法

        Person p2(1,"123456");  //有参构造,括号法

        Person p3(p2);  //拷贝构造,括号法

}
void test 02()

{

        //匿名对象调用

        Person ();  //无参构造,括号法

        Person (1,"123456");  //有参构造,括号法

        Person (p2);  //定义时不允许

}
void test03()

{

       //显示法调用

       Person p= Person();  //无参构造,匿名对象被命名为p

       Person p1= Person (1,"123456");   //有参构造,匿名对象被命名为p1

       Person p2= Person (p1);  //拷贝构造,使用时允许匿名对象被命名为p2     

}
void test04()

{

        //隐式法调用

        //不能调用无参构造

        Person p1={1,"123456"};  //有参构造,小括号变大括号

        Person p2=p1;  //拷贝构造,直接写对象名

        //注:若想不被隐式调用,在构造函数前加上explicit关键字

}

编译器提供的3个函数

  1. 无参构造函数(无参,函数体空)
  2. 析构函数(无参,函数体空)
  3. 拷贝构造(有参,函数体内作值拷贝)

浅拷贝和深拷贝

浅拷贝

class Person

{

public:

       int age;

       char *name;

       Person(int a, char *b)  //有参构造

      {

             age=a;

             name= (char *)malloc(strlen(b)+1);

             strcpy(name,b);   

       }

       Person(const Person & p)  //浅拷贝

       {

            age= p.age;

            name= p.name;  //只做地址值的拷贝

       }

       ~ Person()

        {

               if( name != NULL)

               {

                      free( name);   //同个地址只能被释放一次

                     name= NULL; 

               }

        }

};

深拷贝

拷贝构造函数重写:

Person(const Person & p)  //深拷贝

{

      age= p.age;

      name= (char*)malloc(strlen( p.name)+1);  //重新申请地址

      strcpy(name, p.name);

}

构造函数的初始化列表

class Person

{

public:

       //先定义m1,m2,m3,再赋值a,b,c

        Person(int a,int b, int c) 

       {

              m1=a;

              m2=b;

              m3=c;  

        }

        //定义

        int m1;

        int m2;

        int m3;

}

对比:

class Person

{

public:

       //先声明m1,m2,m3,再定义(定义的顺序与声明的顺序一致)并赋值a,b,c

        Person(int a,int b, int c) :m1(a),m2(b),m3(c)

       {

        }

       //声明

        int m1;

        int m2;

        int m3;

}

多个对象构造(类的嵌套)

在类内先定义,只能调用无参构造

在类内先声明,初始化列表可调用有参构造,构造顺序先构造嵌套里面的类,按声明顺序,再构造嵌套外面的类,析构顺序与构造相反。

动态对象申请


molloc动态申请对象时,不会调用构造函数

Person *p=(Person *) malloc( sizeof( Person));

free释放动态对象时,也不会调用析构函数

free(p);

new动态申请对象时,会调用构造函数

Person *p=new Person;  //调用无参构造

Person *p=new Person(10);  //调用有参构造

void *p=new Person;//调用无参构造,但delete时不能调用析构

delete释放动态对象时,会调用析构函数

delete p;

申请数组空间:

Person *p=new Person[10];  //只能调用无参构造

delete [ ]p;

类的静态成员static


静态成员变量:

  1. 不能在类内初始化,类内只能声明,定义初始化在全局,声明只是限制作用域
  2. 在内存中只有一份,多个对象共享一个静态成员变量
  3. const修饰静态成员变量时,可在类内定义初始化,且静态成员函数可访问
class Person

{

public:

        static int a;    //声明,在编译阶段分配内存(静态全局区),所以访问时可通过作用域(Person::a)或定义一个对象p(p.a)

        const static b=100;   //定义并初始化,在编译阶段分配内存(常量区),同上

}

int Person::a=10;    //定义初始化

静态成员函数:

  1. 能访问静态成员变量,不能访问普通成员变量
  2. 可通过作用域( Person:: show( ) )或实例化对象( p.show( ) )访问
class Person

{

public:

        int a;

       static int b;

       static void show()

       {

              cout<<a<<endl;    //不可访问

              cout<<b<<endl;    //可访问

        }

}

int Person::b=10;

单例模式:

一个类只能实例化一个对象

  1. 无参构造函数私有化(不能实例化一个对象)
  2. 拷贝构造函数私有化
  3. static修饰一个类的指针并私有化(声明),该指针指向new出的唯一对象(要在全局定义初始化)
  4. 提供一个只读的接口访问指针

成员变量/函数的存储


  1. 空类的大小为1字节
  2. 普通成员变量占用类的实例化对象空间大小
  3. 普通成员函数不占用类的实例化对象空间大小,存在代码区
  4. 静态成员变量/函数不占用类的实例化对象空间大小,变量在静态全局区,函数在代码区

this指针


类的成员函数后面都默认加了一个指针常量( Person * const this),即this指针,它指向执行调用该函数的对象

const修饰的成员函数(修饰的是this,为常量指针常量const Person * const this),即为常函数,不能通过this指针修改this指向对象的内容

class Person

{

public:

        int a;

        void show( )

        {

              cout<<a<< endl;  // 即a为this->a

         }

}

void test( )

{

        Person p;   

        p. show( );  // this指向了p

}

友元


全局函数成为类的友元

使该函数可以访问类的私有成员

class Person

{

        friend void print( Person &p);  //声明为友元

public:

        Person(string name, int password)

        {

                 this->name=name;

                 this->password=password;

        }

        string name;

private:

        int password;

};

void print( Person &p)  //全局函数

{

        cout<<p.password<<endl;   //访问私有成员

}

类成为另一个人类的友元

class Data;  //先声明

class Person

{

public:

         Person(string name, int password);  //函数另一写法:类内声明,类外定义

         Data *p;   //此时类Data只有声明,不能实例化,用指针

         void show( )

         {

                   cout<<b->name<<endl;

                   cout<<b-> password<<endl;   //友元后,类Data私有的成员可被类Person访问

          }

}

class Data

{

         friend class Data;    //类Person成为类Data的友元,类Person的函数能访问类Data

         friend void show( );    //类Person的成员函数show()成为类Data的友元, Person::show()函数能访问类Data

public:

         Data(string name, int password)

         {

                 this->name=name;

                 this->password=password; 

         }

         string name;

private:

        int password;

}

//类外定义,注意加上作用域

Person::Person(string name, int password) 

{

          p=new Data(name, password);

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值