C++ 类与对象进阶

1.复制构造函数/拷贝构造函数

===========================================================

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

形如:X::X(X &) 或 X::X(const X & x) 二选一

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

class Complex{
private:
    double real, imag;
};
Complex c1;     // call default constructor
Complex c2(c1); // call default copy constructor to init c2


如果定义自己的复制构造函数,则默认的复制构造函数不存在

class Complex{
public:
    double real, imag;
    Complex(){}                    // constructor
    Complex(const Complex &c){     // self-defined copy constructor
        real = c.real;
        imag = c.imag;
        cout << "copy constructor called";
    }
};
Complex c1;
Complex c2(c1); // output "copy constructor called"


2.类型转换构造函数(感觉暂时没什么用)


3.析构函数

===========================================================

成员函数的一种,名字是(“~”+类名),没有参数和返回值。

一个类最多有一个析构函数。


对象消亡时自动被调用,在对象消亡前做善后工作(释放分配空间)

定义类时没写析构函数,则编译器生成默认析构函数不涉及释放用户申请的内存释放等清理工作。

定义了析构函数,则编译器不生成缺省析构函数

class String{
private:
    char *p;
public:
    String(){
        p = new char[10];
    }
    ~String();
}
String::~String(){
    delete []p;
}

===========================================================

构造函数和析构函数的调用时机

class Demo{
    int id;
public:
    Demo(int i)
    {
        id = i;
        cout << id << " Constructed" << endl;
    }
    ~Demo()
    {
        cout << id << " Destructed" << endl;
    }
};
Demo d1(1);
void func(){
    static Demo d2(2);
    Demo d3(3);
    cout << "func" << endl;
}
int main(){
    cout << endl << "main" <<endl;
    Demo d4(4);
    d4 = 6;
    {Demo d5(5);}
    func();
    cout << "main ends" << endl << endl;
    return 0;
}


函数体外声明的全局变量,函数体内声明的static 变量,在main()结束时析构。

其余变量再起作用域结束时析构。

new 出的动态对象只在 delete 时析构。

===========================================================


4.静态成员变量

===========================================================

静态成员变量本质上是全局变量,哪怕一个对象都不存在,类的静态成员变量也存在。

静态成员函数本质上是全局函数

设置静态成员这种机制的目的是

将和某些类紧密相关的全局变量和函数写到类里面,看上去像一个整体,易于维护和理解


普通成员变量每个对象都有一份,静态成员变量一共就一份,为所有对象共享,作用于全部对象。

访问静态成员可以单并不必须通过对象。

class CRectangle{
private:
    int w, h;
    static int nTotalArea;
    static int nTotalNumber;
public:
    CRectangle(int w_, int h_);
    ~CRectangle();
    static void printTotal();
};
cout << sizeof(CRectangle); // output: 8
CRectangle::printTotal();   // visit printTotal() through class not object
                            // like an global function

sizeof(myclass) 运算符不会将计算静态成员变量大小计算在内

-----------------------------------------------------------

静态成员变量 的例子

class CRectangle{
private:
    int w, h;
    static int nTotalArea;
    static int nTotalNumber;
public:
    CRectangle(int w_, int h_);
    ~CRectangle();
    static void printTotal();
};
CRectangle::CRectangle(int w_, int h_)
{
    w = w_; h = h_;
    nTotalNumber ++;
    nTotalArea += w*h;
}
CRectangle::~Rectangle()
{
    nTotalNumber--;
    nTotalArea -= w*h;
}
void  CRectangle::printTotal()
{
    cout << nTotalNumber << "," << nTotalArea << endl;
}
int CRectangle::nTotalNumber = 0;
int CRectangle::nTotalArea = 0;
// 必须在定义类的文件中对静态成员变量进行一次初始化
// 否则编译能通过,连接不能通过。

int main()
{
    CRectangle r1(3,3), r2(2,2);
    CRectangle::printTotal();
    r1.printTotal();
    return 0;
}

-----------------------------------------------------------

注意事项:

静态成员函数中,不能调用非静态成员变量,也不能调用非静态成员函数

因为静态成员函数无法弄明白非静态成员属于哪个对象。

在使用CRectangle类时,有时候会调用复制构造函数生成临时的隐藏的CRectangle对象

        调用一个以CRectangle类对象作为参数的函数时;

        调用一个以CRectangle类对象作为返回值的函数时;

临时对象在消亡时会调用析构函数,减少nTotalNumber和nTotalArea的值

可是在这些临时对象生成时却没有增加 nTotalNumber和nTotalArea的值。

解决办法:为CRectangle类写一个复制构造函数

CRectangle::CRectangle(CRectangle &r)
{
    w = r.w; h = r.h;
    nTotalNumber++;
    nTotalArea += w*h;
}

===========================================================


你可能感兴趣的:(C++ 类与对象进阶)