C++之类的引入

C++之类的引入

一、结构体到类的演变

C语法

  • 定义新的数据类型,该新的数据类型称之为结构体,成员为各种数据类型的变量。
  struct stu 
   {
     char age;
     int  greade;
   };
   stu stu1;  //用新的数据类型结构体定义变量

C++语法

  • 定义新的数据类型该新的数据类型称之为类,成员不仅可以包含变量数据,还包含着方法,也称操作函数。
   class stu
   {
     char age;
     int greade;
     void operate()
        {
           cout<<"hell a new data is create<<endl";
        }
   };
   stu stu1;  //用新的数据类型类定义变量(C++这里的用类定义的变量称为对象)

二、对象的定义与使用

2.1、栈上定义对象

   //方式1、 先声明类,再定义对象
       class stu
       {
         char age;
         int greade;
         void operate()
            {
               cout<<"hell a new data is create<<endl";
            }
       };
       stu stu1;  		//第一种定义对象的方法
       class stu stuq; //第二种定义对象的方法
   //方式2、声明类同时定义对象
      class stu
       {
         char age;
         int greade;
         void operate()
            {
               cout<<"hell a new data is create<<endl";
            }
       }stu1;
//方式3、没有类名,直接定义对象
  class
   {
     char age;
     int greade;
     void operate()
        {
           cout<<"hell a new data is create<<endl";
        }
   }stu1;

2.2、堆上定义对象

2.2.1、堆上普通数据类型的定义

C语言中提供了 malloc 和 free 两个系统函数,完成对堆内存的申请和释放。而 C++则提供了两关键字 new 和 delete。

//整形类型的定义
int main()
{
	// int *p = (int*)malloc(sizeof(int));
	int *p = new int(10); //new
	*p = 100;
	cout<<*p<<endl;
	int **pp = new int *; // (int**)malloc(sizeof(int*))
	Stu *ps = new Stu;
	return 0;
}
//一维数组的定义
int main()
{
	// new float [10] malloc(10*sizeof(float);
	float *p = new float [10]{1.2,3.4};
	for(int i=0; i<10; i++)
	{
		cout<<p[i]<<endl;
	}
	char **pp = new char *[11];
	for(int i=0; i<10; i++)
	{
		pp[i] = "china";
	}
	pp[10] = nullptr;
	while(*pp)
	{
		cout<<*pp++<<endl;
	}
}

注意事项
1 new/delete 是关键字,效率高于 malloc 和 free。
2 配对使用,避免内存泄漏和多重释放。
3 避免,交叉使用。比如 malloc 申请的空间去 delete, new 出的空间被 free。

  • 如果只是以上的功能, C中的 malloc 和 free 完全可以胜任, C++就没有必要更进一步,引入这两个关键字。重点用在类对象的申请与释放。申请的时候会调用构造器完成初始化,释放的时候,会调用析构器完成内存的清理。(见下文)

2.2.2、堆上类对象的定义
//1、new创建类对象例子:
CTest* pTest = new CTest();  //pTest用来接收类对象指针。
delete pTest;
//2、不用new,直接使用类定义申明
CTest mTest;

/*此种创建方式,使用完后不需要手动释放,该类析构函数会自动执行。而new申请的对象,则只有调用到delete时再会执行析构函数,如果程序退出而没有执行delete则会造成内存泄漏。*/
//3、只定义类指针
CTest *mTest = NULL;
mTest = new CTest();

1、这跟不用new申明对象有很大区别,类指针可以先行定义后赋值,类指针只是个通用指针,在new之前不为该类对象分配任何内存空间。
2、用普通方式创建的类对象,在创建之初就已经分配了内存空间。而类指针,如果未经过对象初始化,则不需要delete释放。


//4、new对象指针作为函数参数和返回值

// 下面要示意一下类指针对象作为返回值和参数使用
class CTest 
{  
public:   
    int a;  
};    

class CBest 
{ 
public:  
    int b;  
};   

CTest* fun(CBest* pBest) 
{   
    CTest* pTest = new CTest();   
    pTest->a = pBest->b;
    return pTest;  
}    

int main() 
{   
    CBest* pBest = new CBest();   
    CTest* pRes= fun(pBest);     

    if(pBest!=NULL)    
        delete pBest;   
	if(pRes!=NULL)    
        delete pRes ;   
    return -1;  
}
  • new创建对象的特点:
    1、new创建类对象需要指针接收,一处初始化,多处使用
    2、new创建类对象使用完需delete销毁
    3、new创建对象直接使用堆空间,而局部不用new定义类对象则使用栈空间
    4、new对象指针用途广泛,比如作为函数返回值、函数参数等
    5、频繁调用场合并不适合new,就像new申请和释放内存一样

  • new与非new作用域
    1、不用new:作用域限制在定义类对象的方法中,当方法结束时,类对象也被系统释放了。(安全不会造成内存系统泄漏)。
    2、用new:创建的是指向类对象的指针,作用域变成了全局,当程序结束时,必须用delete删除,系统不会自动释放,(不注意可能造成内存泄漏)。

三、类的大小

备注:以下内容摘自:https://www.cnblogs.com/sz-leez/p/7119232.html

1.空类
class A
{
};

sizeof(A); //1
解析:类的实例化就是为每个实例在内存中分配一块地址;每个类在内存中都有唯一的标识,因此空类被实例化时,编译器会隐含地为其添加一个字节,以作区分。
2.虚函数类
class A
{
    virtual void Fun();
};

sizeof(A); //4
解析:当一个类中包含虚函数时,会有一个指向其虚函数表的指针vptr,系统为类指针分配大小为4个字节(即使有多个虚函数)。
3.普通数据成员
class A
{
    int a;
    char b;
};

sizeof(A); //8

解析:普通数据成员,按照其数据类型分配大小,由于字节对齐,所以a+b=8字节。
4.静态数据成员
class A
{
    int a;
    static int b;
};

sizeof(A); //4

解析:
1、静态数据成员存放的是全局数据段,即使它是类的一个成员,但不影响类的大小;不管类产生多少实例或者派生多少子类,静态成员数据在类中永远只有一个实体存在。
2、类的非静态数据成员只有被实例化时,才存在。但类的静态数据成员一旦被声明,无论类是否被实例化,它都已存在。类的静态数据成员可以说是一种特殊的全局变量。
5.普通成员函数
class A
{
    void Fun();
};

sizeof(A); //1
解析:类的大小与它的构造函数、析构函数以及其他成员函数无关,只与它的数据成员相关。
6.普通继承

class A
{
    int a;
};

class B:public A
{
    int b;
};

sizeof(B); //8

解析:普通类的继承,类的大小为本身数据成员大小+基类数据成员大小。
7.虚函数继承

virtual class A
{
    int a;
};

class B:virtual public A
{
    int b;
};

sizeof(B); //12

四、类的访问权限

  • C中struct 的所有行为和属性都是 public 的(默认),此举也是为了 C++兼容 C 语言,因为 C 语言中没有权限的概念。

  • C++中的 class 是由C中struct演变而来。C++不同与C,它对外屏蔽了部分数据,只提供对外的接口。但C++中class可以指定行为和属性的访问方式,若不指定默认为 private。
类内成员属性 类内部访问权限 对象访问权限
public 可访问 可访问
private 可访问 不可访问

五、类的存储方式

用类去定义对象时,系统会为每一个对象分配存储空间。如果一个类包括了数据和函数,要分别为数据和函数的代码分配存储空间。

  • 1、存在问题:如果用同一个类定义了 10 个对象,那么就需要分别为 10 个对象的数据和函数代码分配存储单元?

  • 问题解析:如果按上述方法,那样会大大的浪费内存空间,C++编译器在分配时只对各个对象的数据部分单独分配内存,对象的函数体分配的是同一段公用的内存。

  • 2、存在问题:既然函数代码段调用的是同一个,各对象的在调用时怎么知道当前是哪个对象在调用本函数?

  • 问题解析:C++在对象在调用公用函数时,将对象的指针(This)作为参数隐士的传递给了公用函数用来识别当前调用者对象。
原文地址:https://www.cnblogs.com/retry/p/9308915.html