C++基础之面向对象(一)

来源:互联网 发布:天刀无缺染色数据 编辑:程序博客网 时间:2024/06/06 21:31

一、

对象本身是占内存的,但是类是对象的描述(相当于类型int),不占内存


二、

类中实现的函数默认为inline函数

但如果类中只是函数的声明,而函数的实现在类外。则若需要使函数为inline函数,需要自己在函数名前先加inline

 

三、

计算机对所有函数在程序区中都只有一份拷贝,此外静态区变量在内存中也只有一份拷贝,内存地址是固定的


四、this指针

所有类对象都会到程序区中调用同一成员函数(print),(但是计算机怎么知道要输出哪一个对象的信息?)

因为有this指针!(this指针代表当前对象的地址,this指针的计算是计算机自动完成的)每个对象调用成员函数时,都会将对象地址先传到this指针中。

 

计算机什么时候会计算this指针?

若函数是实例函数(若类中函数前有static关键字则为静态函数,否则为实例函数),则计算机会自动生成计算this指针,而不会对静态函数计算this指针。

 

五、static

静态成员变量/类变量(存放在静态区,编译时,内存地址就固定,内存中只有一份拷贝,程序结束才释放)。

静态成员变量需要给它全局初始化,就是给他分配空间,而且这个分配空间一定在main函数之前完成,因为编译时要知道静态成员变量的地址!(一般在.cpp文件中初始化,因为在.h文件中可能会被多次包含)

   实例化变量,只能在实例化完对象后才能访问

   实例函数,只能在实例化完对象后才能被调用(因为每次要计算this指针)

静态变量/类变量(存放在静态区,编译时,内存地址就固定,内存中只有一份拷贝,程序结束才释放)无需实例化对象便可以访问

类的静态函数不需要实例化对象就可以被调用。

类的静态函数和静态变量在声明时加上static,定义时不需要加static。

类的静态变量和静态函数的调用方式:

即可以通过类名调用:

CStudent::tt=100;//调用类中的静态变量

CStudent::test();//调用类中的静态函数

也可以通过对象来调用:

CStudent stA;

stA.test();

六、构造函数和析构函数

 1>构造函数的调用者是计算机系统,程序员不能直接调用.构造函数作用:初始化成员变量

 2>实例化对象时,由系统直接调用.

 3>若程序员不写任何构造函数,则系统会自动添加默认构造函数(参数为空),若程序员写了一个构造函数,则系统不会自动添加默认构造函数。如果类中有多个构造函数,按照重载函数调用的规则调用。

    4>拷贝构造函数====》特点:至少有一个参数是本类型的引用

若程序员不写任何拷贝构造函数,则系统会自动添加默认拷贝构造函数(有一个参数,此参数类型为本类型的一个引用),若程序员写了一个拷贝构造函数,则系统不会自动添加默认构造函数。

 5>对象间直接赋值时,系统会自动调用拷贝构造函数。根据已有对象实例化新对象时系统自动调用拷贝构造函数。拷贝构造函数使用值拷贝(浅拷贝-->对于指向堆区的指针变量有影响==>内存泄漏)

解释:


经过拷贝后,id、name、p、age都有两份,但是指针p指向的堆区只有一份。

解决:

class CStudent{private:int id;string name;//实例变量int age = 0;public:int *p=NULL;CStudent(int id, string name, int age) {this->id = id;this->name = name;this->age = age;p = new int(10);}CStudent(CStudent &t)//自己写的拷贝构造函数------【默认拷贝构造函数(使用浅拷贝)】{this->id = t.id;this->age = t.age;this->name = t.name;//以下这段代码可以防止不同对象的p指针指向同一堆区//===============================if (this->p != NULL){delete p;}this->p = new int;//新建堆区*(this->p) = *t.p;//=============================}~CStudent(){if (this->p != NULL)//释放堆区空间,防止内存泄漏{delete p;}}}

七、Const

(1)变量

int a;

const int a=2;//a中的值是不能发生变化的,定义常量时,应该立刻给其赋初始值。

也可以写成int const a = 2;  [a=a+2  X错误]

 

(2)指针

int const *p;//常量指针。指针指向的是一个整型常量,p不是常量,p是变量。//也可以写成const int *p;int *const p;//指针常量。p本身就是一个常量,定义时需要初始化,p所指向的地址处的内容可以发生变化。//p不能指向整型常量

(3)class对象声明中  常对象(所有成员变量都是常量,不能修改)

通过常对象只能调用常函数,但是常函数可以被该类的任何对象(常对象或者非常对象)访问

const CStudent stA(赋初始值)void CStudent::print() const   //const写在后面{ }//常数据成员变量要用参数列表进行初始化    【假如id是常数据成员变量】CStudent(int id, string nameA) :id(id), name(nameA)//先赋值id,再赋值name{}//或者CStudent(int id, string nameA) :id(id)//先赋值id,再赋值name{ this->name = t.name;}

八、指针

1)

void(CStudent::*p2)();

p2 = &CStudent::print;//类的函数指针和之前的函数指针不同

(stA.*p2)();//必须要这样定义和调用


2)

this指针是指针常量,this ==>(Time为类) Time* const this; this=&a;(a为类对象)

this指向的地址处的内容可以变化,this本身(指向)不能发生变化


3)

C中calloc/malloc函数开辟内存,用free函数释放内存,若开辟失败则程序异常蓝屏。

C++中用new关键字开辟内存,用delete关键字释放内存,开辟失败则指针返回NULL

【安全】  if(p!=NULL)


九、防止内存泄漏的三个原则:

1、函数{}内new和delete要成对出现。

2、类中属性(成员变量)在构造函数中用new开辟,在析构函数中释放

3、不使用return语句返回新对象==>需要返回的对象变为指针参数进行传递。