【笔记-C++】 class

来源:互联网 发布:用友软件 t系列 编辑:程序博客网 时间:2024/06/05 00:25

与结构体区别

struct包装数据,函数包装代码,类既包装数据,也包装代码

classstruct都可以描述对象

 

struct可以使用{..............}初始化对象,class只有在最新的标准才可以使用这种初始化的方法(需要public

struct A

{

void fun(){cout<<"xxx"<<endl;}

int a;

double b;

};

可以使用A a={1,1.2};

如果把struct换成class则可能无法使用该种赋值方式

权限

struct默认是完全公开的,class默认是私有的

private:只有在类内可以使用

public:在类内外都可以使用

class中加public:则此语句下的内容都可以在类外和类内访问,直到遇到下一个权限的修饰语

class  A{..................};

A  a;  构造函数无参时,此行不可写成A  a()

A  *p=new A();

      new 后放的是A的构造函数

类的基本函数

class A{......

   public: (如果定义构造函数,则不能省略)

 

                        A(){......}

构造函数重载     A(int  xint  y)a(3),b(x),y(y)初始化参数{.....}

                        A(int  x=1){....}

拷贝构造           A(const  A&a){.....}

稀构函数       ~A(){........}


声明和实现分开时:初始化参数列表放在实现部分,参数的默认值在声明部分指定,函数前的static修饰放在声明处,函数的const修饰在声明和实现部分都写。

构造、析构都有系统默认的,如过要自定义,会覆盖系统的。此类函数无返回值

拷贝构造内的A&a可以不写a,如果拷贝构造的操作中有需要使用a,才必须写上

构造函数

构造函数在对象创建时调用一次

A  a;  创建一个栈对象,同时调用无参构造

A  a(10); 创建一个栈对象,调用有参构造(传入参数10

 

A  *p=new  A();  创建一个堆对象,同时调用无参构造(无参构造时也可用 A  *p=new  A

 

A(x=1)A()在使用A()调用时会产生冲突

 

const变量只能在初始化时赋值(初始化参数列表中进行),初始化参数列表中写成A(),如果A是基本类型,A的值变为0,如果A是类类型,则为无参构造(继承中用)

拷贝函数

拷贝构造函数调用时间:在使用同类型的对象构建一个对象(复制);在函数参数值传递;函数返回对象一旦有拷贝操作就调用

使用时:A  a;   A  b=a;

不可写成A  aA  b;  b=a

1)A  get(){A  areturn a;}

   A   c=get();

        不用拷贝构造,系统自动优化

2A  get(){A  *a=new  A(); return *a;}

   A   c=get();

       会调用拷贝构造,因为使用了堆

自定义拷贝构造时,必须同时定义构造函数,不可以只定义拷贝构造(可以只定义构造,不定义拷贝)

析构函数

析构函数中执行释放内存可能会造成内存泄漏。

 

在栈中将class创建出对象后,会在程序某行之后不再出现该对象时,自动调用析构函数(在最后一次出现对象的行调用)

析构函数用来释放内存

可单独调用~A()  堆内层时必须单独调用析构,因为堆内存不会自动调用析构函数

expA  *a=new  A();

     a->~A()

虚析构函数

(在析构前加virtual),基类有虚函数,基类对象的指针指向子类对象(多态条件时),释放基类对象的该指针时,如果基类析构函数不是虚函数,则子类析构函数的调用行为未定(不调用),把基类中析构变为虚函数,则会调用子类构造,同时也会调用基类的析构。

构造函数不能为虚函数(拷贝构造,构造)

深拷贝

当要拷贝的对象中有指针变量时,会使用拷贝前后两个对象中的指针指向同一块堆内存,在其中一个对象释放堆内存后,另一对象中指针指向的是一块已经释放的内存,再次释放会出错,解决此问题需要使用深拷贝方式(自己定义拷贝过程)

class  A{

       int  m

       int  *n;

A():m(10),n(new int(8)){}

A(const A&a):n(new  int){

           m=a.m;   *n=*(a.n);  

     }

~A(){

       if(n=NULL){delete  n; n=NULL;}

      }

}

1)构造函数为指针分配堆内存

2)拷贝构造函数为拷贝出的对象的指针分配新的堆内存,并进行其他数据的拷贝

3)自定义析构函数释放堆内存(也可以不使用if语句进行判断,因为有时候没有给类的指针成员分配内存,而是指向null,可以不用释放,delete NULL也不会出问题)

因为有了1)3)所以才需要2)的步骤。

拷贝构造和赋值函数

编译器会自动生成缺省的拷贝构造和赋值函数,如果不想编写这两个函数,也不希望默认的被调用,则可以将这两个函数声明为私有的。

this指针

this是指向当前对象的指针,*this代表当前对象。构造对象时,指向正在构建的对象,成员函数中,指向这个函数的对象

当函数形参与成员变量重名时,可以用this区分:

class  A{

     int b;

   public:

     A(int b){this->b=b;}

};

可使用this返回数据,可作为参数传递

静态成员、函数

静态成员:类和类的对象所共享的函数、数据(相当于全局变量、函数,存在于全局区,不属于对象,只是访问范围限制在类内),不需要对象,只需要类型就可以访问。

 

声明和实现分开时,函数前的static修饰放在声明处。

静态成员必须在类外(全局区)进行初始化操作,不能在类的初始化中进行赋值。

class  A{ public: static  int  x;};

int  A::x=0;      

 

类内函数或类的对象,能直接访问类内的静态变量、函数。

类外调用静态成员、函数[需要是public]

A::x;

A::fun();

 

静态函数只能直接访问静态成员,不能直接访问非静态成员,因为无this指针。如果想在静态函数中访问非静态成员,可以传入一个指针:

static void ab(A *a){  cout<<a->m<<endl;}

成员指针

typedef void (A::* FUN)(int a);

类型是:void (A::*)(int);

 

//赋值

FUN f = &A::f1;

 

 

使用:

(a.*f)()

(this->*f)()

 

成员指针直接输出时为1

用联合可以输出指针指向的地址

union{int  A::*p;  void *pr;};

pr可以输出指向的地址

const对象和函数

const对象只能调用const函数,声明和实现分开时,函数的const修饰在声明和实现都需要写。

1)const  A  a;    const对象

2)void  ab() const{..........}     const函数(类内)

  void  ab(){.................}

以上两个函数构成重载(非const函数优先调用非const函数,如果无非const函数,就用const

const函数不能修改普通成员变量,如需修改,则在成员前加mutable修饰

expmutable  int  m

      void  ab()const{m=10;}

友元

友元函数:在全局函数中要调用类中私有成员,需要在类中用friend声明一下这个全局函数。则该全局函数可访问到类中私有成员(通过类的对象)

exp:

class  A{int x;};

A  a;

void ab(A  a){cout<<a.x<<endl;}

class改为:

class  A{

int  x;

friend  void  ab();

};

 

友元类:

friend  class  B

B继承A时,使用友元类,可以使B能访问到Aprivate成员

原创粉丝点击