类和对象

来源:互联网 发布:杀女婴知乎 编辑:程序博客网 时间:2024/05/13 17:26

复制构造函数

只有一个参数,即对同类对象的引用
形如

X::X(X&)X::X(const X &)//能以常量对象作为参数,二者选一

如果没有定义,编译默认生成。默认的复制构造函数完成复制功能。

class Complex{    private:        double real,iamg;}Complex c1;//调用缺省无参构造函数Complex c2(c1);//调用缺省的复制构造函数,将c2初始化和c1一样

起作用的三种情况
1)当用一个对象去初始化同类的两一个对象时
2)若果某函数有一个参数是类A的对象,那么该函数被调用时,类A的复制构造函数将被调用

#include <iostream>using namespace std;class A{public:    A(){};    A(A &a){        cout<<"Copy constructor called"<<endl;    }};void Func(A a1){}int main(){    A a2;    Func(a2);    return 0;}

输出结果

Copy constructor called//形参a1的值并不等于实参a2

3)若果函数的返回值是类A的对象,则函数返回时,A的复制构造函数被调用
为什么要自己写复制构造函数

类型转换构造函数

实现类型的自动转换
只有一个参数,不是复制构造函数
编译系统会自动调用,调用的时候,会建立一个临时对象/临时变量

析构函数(Destructor)

成员函数的一种
名字与类名相同
在前面加”~”
没有参数和返回值
一个雷最多只有一个析构函数
在对象消亡时,自动被调用,在对象消亡前做善后工作,如释放分配的内存空间等
定义类的时候没写析构函数,则编译器生成缺省析构函数。
调用说明
1)对象数组生命期结束时,对象数组的每个元素的析构函数都会被调用

#include <iostream>using namespace std;class Ctest{public:    ~Ctest()    {        cout<<"destructor called"<<endl;    };};int main(){    Ctest a[2];    cout<<"end main"<<endl;    return 0;}

输出

end maindestructor calleddestructor called

2)delete运算导致析构函数被调用

int main(){    Ctest *pTest;    pTest= new Ctest[3];    delete[] pTest;}

输出

destructor calleddestructor calleddestructor called//数组里包含三个对象,析构函数被调用三次

先构造的,后析构
后构造的,先析构

静态成员变量和静态成员函数

静态成员:加入static关键字
普通成员变量每个对象有各自的一份,而静态成员变量一共就一份,为所有对象共享
sizeof 运算不会计算静态成员变量
普通成员函数必须作用于某个对象,静态成员函数并不具体作用于某个对象,因此静态成员不需要通过对象就能访问。
静态成员变量本质上是全局变量,哪怕一个对象都不存在,静态成员变量也存在。
静态成员访问方式
1)类名::成员名
2)对象名.成员名
3)指针->成员名
4)引用.成员名
在静态成员函数中,不能访问非静态成员变量,也不能调用非静态成员函数。

this指针

指向成员函数作用的对象

class A{    int i;public:     void hello(){cout<<"hello"<<endl;}};int main(){    A *p=NULL;    P->Hello();}

看上去是有问题的,p为空指针,并没有指向实际的A对象,那么p如何调用Hello?实际上

void hello(){cout<<"hello"<<endl;}

编译时,会等价于

void hello(A *this){cout<<"hello"<<endl;}

p->Hello 翻译为 Hello(p);//p作为参数,输出Hello
再看下边一段代码

class A{    int i;public:     void hello(){cout<<i<<"hello"<<endl;}};int main(){    A *p=NULL;    P->Hello();}
void hello(){cout<<i<<"hello"<<endl;}等价为void hello(A *this){cout<<this->i<<"hello"<<endl;}

此时,this为空指针,调用Hello(p)会出错
总结
静态成员函数不作用于任何对象,故不能使用this指针。静态成员函数的真实参数的个数,就是程序中写出的参数个数。

常引用

引用前加const关键字,成为常引用,不能通过常引用,修改其引用的变量
作用
当对象作为函数的参数的时候,生成该参数需要调用复制构造函数,效率比较低。用指针作为参数,会影响代码的美观。此时,可以将对象的引用作为参数。

class Sample{…};void PrintfObj(Sample &o){…};

对象作为函数的参数也有一定的风险性,若函数中不小心修改了形参o,则实参也跟着变,为了避免这种现象:采用对象的常引用作为参数

void PrintfObj(const Sample &o){…};

这样,函数中就能确保不会出现无意更改o值的语句了