C++快速复习1

C++快速复习


本文旨在通过快速的罗列自己曾经的C++代码实现,帮助自己快速复习已经掌握的知识:

类的构造函数知识:

三种构造函数:
1.无参数的构造函数;myclass (){} 调用:myclass M;
2.有参数的构造函数;myclass(int a,int b){} 调用: myclass M2(1,3);
3.拷贝构造函数;myclass (const myclass & obj) myclass M1(1,4);myclass M3=M1;

#include<iostream>
using namespace std;
class myclass
{
public:
       myclass()//这个是无参数的默认构造函数;
       {

       }
              myclass(int a, int b)//有参构造函数
       {
              this->a = a;
              this->b = b;
       }
       myclass(const myclass & M)//复制构造函数,在这个构造函数中,用来初始化另新对象的旧对象更像是结构体,因为可以使用.来访问他的成员变量。
       {
              a = M.a;
              b = M.b;
       }
       void show()
       {
              cout << "a=" << a << " b=" << b << endl;
       }
private:
       int a;
       int b;
};
int main()
{
       myclass C1(1, 2);
       C1.show();
       myclass C2 = C1;//这里会调用复制构造函数,myclass (const myclass& M),也可以写成C2(C1);
       myclass C3;//这里会调用无参的构造函数,不能写成myclass C3();
       C3 = C1;//这里是一个operator=的操作,编译器会默认的提供,当然也是可以重载的 myclass& operator =(const myclass & obj)
       C3.show();
       return 0;
}

拷贝构造函数的调用时机:
1.在程序中根据一个旧的对象创建一个新的对象:

   myclass C3 = C1;

2.在将对象作为函数参数进行传递的时候:

void Print(myclass temp)
{
     cout<<"这个时候就调用了copy构造函数”<<endl;
}

int main()
{
    myclass M;
    Print(M);//这个函数是传值的,在函数中会产生一个临时的对象,是由copy构造函数来创建的,在函数结束的时候会调用析构函数
}

3.在将对象作为返回值的时候,会根据函数中产生的一个旧的对象来构造一个需要返回的对象:
有关于匿名对象:
匿名对象实际是在函数返回值是在函数中定义的对象的时候产生的,因为在函数中产生的对象实际在函数结束的时候会被回收(析构函数),所以返回对象就会产生一个匿名对象(通过的是copy构造函数)来保存返回值
例如:

myclass Getone()
{
    myclass M(1,2);//这里会调用有参数的构造函数;产生一个对象;
    return M;//返回值是在函数中产生的对象的时候就会同时产生一个匿名对象,该匿名对象的产生是由copy构造函数产生的;
}
//函数结束的时候会调用析构函数,将M这个函数对象析构,函数返回一个匿名对象

匿名对象后期的存在与否看是否将其声明为一个新的对象:
函数返回的值是对象的时候和形式如myclass(1,2)都会产生匿名对象;
1.将匿名对象声明为一个新的对象,则该新对象不用再次调用构造函数,而是直接给匿名对象命名

myclass M1=Getone();//M1不会再次去调用构造函数,而是将匿名对象直接命名,加以使用,同时也不会析构该匿名对象
2.将匿名对象通过赋值给另一个已经存在的对象,赋值之后,会将匿名对象析构掉

M1=Getone();//在赋值完成之后,匿名对象会被析构掉

默认构造函数:
1.如果没有定义一个默认的构造函数,编译器会生成一个无参数的默认构造函数,函数体是空的;
2.如果没有定义一个copy构造函数,编译器会生成一个默认的copy构造函数,函数中完成基本成员变量的复制;
构造函数的调用规则:
只有在任何的构造函数都没有被提供的时候,C++编译器才会提供一个没有参数的构造函数;只要是有构造函数了,C++编译器就不会提供默认无参数的构造函数;
言外之意就是说,只要是你定义了的构造函数就必须使用;
深拷贝和浅拷贝:
所谓浅拷贝,是指根据一个旧的对象产生一个新的对象的时候,将对象中的成员数据进行简单的拷贝赋值,默认的拷贝构造函数是浅拷贝的,只是成员变量之间的简单赋值;
深拷贝是相对于浅拷贝来说的,是指在进行拷贝的时候,不是简简单单的进行成员变量之间的复制,也包含有其他的操作,如:相应指针的指向空间的申请,类中对象的计数等等;
与浅拷贝类似的等号操作符:
在进行对象之间的赋值的时候,比如已经产生的变量obj1 obj2;obj1=obj2;这个操作其实也是一种浅拷贝,如果想要改成深拷贝的话,需要将operator=这个操作符
一种格式:

myclass & operator =(const myclass& M)
{
      ...
     return *this;
}

构造函数的初始化列表:
引出:当一个类中包含另一个类对象的时候,被包含的类只提供了有参数的构造函数,那么包含这个类的类也必须提供有参数的构造函数;
或者是类中含有const常量的时候,需要在初始化的时候对const常量进行初始化;
这个时候就可以使用构造函数的初始化列表的方法来初始化类对象:

class A
{
private:
     int a;
     const int H;
public :
 A(int a):H(100)
{
   this->a=a;
}
}

class B
{
  private:
     int b;
     A C;//b类对象中包含A类的对象,而A类只提供了一个有参数的构造函数,此时对于A类编译器将不再提供默认的无参构造函数
  public:
     B(int m,int k):b(m),C(k)//这里使用的是初始化列表的方式,对B类中的所有的数据进行了初始化;当然,这种方式也等可以同于在函数体中的实现
{

}
}

初始化列表的时候,被包含的类的初始化、先于包含的类的初始化,而如果包含的类中包含有多个其他的类对象,则他们产生的类对象(调用各自的构造函数)的顺序是按照在包含的类中的定义的顺序;
例如:如果B中包含A a1;Aa2:程序会先生成a1对象,即使在初始化列表中a2在前(即 B(int a,in b):a2(b),a1(a){});所以决定对象产生的顺序不在于初始化列表而在于定义的顺序;
点击new和delete:
1.new和delete用于常规变量:
new的返回值是一个指针,delete只能操作new出来的内存空间:

int * a=new int(10);//返回指针并将其初始化成10;
....
delete a;

new 一个一维数组的格式,delete释放一个一维数组的格式:

int *arr=new int [N];
.....
delete[] arr;

new二维数组,delete释放二维数组的格式:

int * * Arr=new int * [N];
for(int i=0;i<N;i++)
{
   Arr[i]=new int[M];
}//产生一个arr数组N*M大小的
.......
for(int i=0;i<N;i++)
delete [] arr[i];
delete [] arr;

2.new 和delete用于类对象:

myclass * p=new myclass(10);//这里是调用了类的构造函数

new delete和malloc free 的区别在于:malloc只是简单的申请内存类型转化,而不是调用类的构造函数,new则会调用类的构造函数,同样,delete会执行析构函数free则不会调用;
静态成员变量:

这是一种属于整个类的变量,所有的属于这个类的对象都是可以访问的,应用有计数器(记录所有的对象的数目)

class myclass
{
public:
private:
       int a;
       int b;
       static int c;//static将C声明成一个属于类的变量,类的所有的对象都可以访问该变量
};
int myclass::c = 10;//该静态成员变量的初始化是在类的外面,格式是<数据类型> 类名::变量名=变量值

静态成员函数:
这是一种属于这个类的函数,每个属于该类的对象都可以调用,但是这个函数并没有访问对象中成员函数的权限,它只是属于整个类,访问的方式有:

class myclass
{
public:
static void GetC()//这个函数就是一个静态成员函数,所有的对象都具有访问权限,但是这个函数不能访问某个对象的成员变量
{
  cout<<c<<endl;//一般来说,静态成员函数要使用的是静态成员变量,
}
private:
       int a;
       int b;
       static int c;//static将C声明成一个属于类的变量,类的所有的对象都可以访问该变量
};
int myclass::c = 10;

1.通过类的对象来访问:

myclass C;
C.GetC();//每一个对象都可以访问该成员函数

2.通过类直接访问:因为静态的成员函数是属于整个类的,所以可以通过::来访问

myclass::GetC();//这个类的访问

C++面向对象模型:

class C2
{
public:
int i;//4位
int j;//4位
int k;//4位
private:
static int m;//4位
public:
void getI();//在32位系统中存储函数的起始地址,也是32位
void GetJ();
}//

C2 C;
cout<<sizeof(C)<<endl;//结果是12,因为C++管理数据和函数的方式是分开的,成员函数和数据是不在一起的,同时static修饰的变量属于整个类,被放置在全局变量中,
//而成员函数被单独放置,整个类共用成员函数,成员函数在调用的时候其实是将this指针作为参数传递,而static修饰的静态成员函数是属于整个类的,它在调用的时候是不会
//将this指针传递过去的,因为静态成员函数是不能访问对象中的私有成员变量的。而在取一个对象的大小的时候,只去取其特有的变量的大小的总和,即上述例子中的 i j
// k三个变量的大小之和

this指针:
this指针总是指向当前操作的对象,想要访问当前对象的数据成员,使用->即可

class C1
{
   public:
    void Add(const C1& C)//在类中访问其成员变量是可以通过.来完成的,即使是要操作另一个对象
    {
          this->a+=C.a;
          this->b+=C.b;
    }
   private:
int a;
int b;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值