抱歉,您的浏览器无法访问本站

本页面需要浏览器支持(启用)JavaScript


了解详情 >

马上考试了,好紧张,赶紧学点。。

成员对象和封闭类

一个类的成员变量如果是另一个类的对象,则该成员变量称为“成员对象”。这两个类为包含关系。包含成员对象的类叫封闭类。

执行封闭类的构造函数时,先执行成员对象的构造函数,然后执行本类的构造函数。

当封闭类对象消亡时,先执行封闭类的析构函数,然后在执行成员对象的析构函数,成员对象析构函数的执行次序和构造函数的执行次序相反。

友元

友元函数的目的是访问类的私有成员。

友元类的关系不具有传递性也不具有对称性

this指针

调用一个成员函数时,编译器自动向函数里传入this指针,该指针指向调用该函数的对象的指针。

静态成员是类具有的属性,不是对象的特征,所以静态成员函数不具有this指针

运算符重载

赋值运算符和地址运算符系统提供了默认重载。对于赋值运算符系统默认重载为对象成员变量的复制,对于地址运算符系统默认重载为返回任何类对象的地址。

运算符重载的写法:

void operator = (args){
    // dosomething...
}

运算符重载表示为成员函数和友元函数

运算符重载表示为类的成员函数时,对于二元运算符只需要传递一个参数,参数数量总是少一个

运算符重载表示为类的友元函数是,对于二元运算符需要传递两个参数

使用成员函数虽然方便,对于重载+运算符,只能将对象放在左边,例如:

Object operator + (const int &other){
    return this->num + other;
}
int res = obj + 1;	// access √
int res = 1 + obj; // error ×

所以只能使用友元函数将两个参数都列出来,即可解决问题。

重载赋值运算符

赋值运算符必须重载为成员函数。

因为等号通常连用,所以operator = 函数通常要返回引用。

浅拷贝和深拷贝

对于以下使用复制构造函数时,系统会进行浅拷贝:

Object p1;
Object p2(p1);
Object p3 = p1;

此时如果Object类中有定义指针成员变量,复制构造函数会将指针的值(指针里面存的是地址)原封不动复制过去,这样每个对象里存的地址虽然地址存放的空间是新开辟的空间,但地址所指向的值是同一个地址。这样,当p1的指针成员变量改变时,p2、p3存放的指针变量的值都会跟着改。

浅拷贝的坏处:

当p1消亡时,需要释放构造函数中动态申请的空间,而当对象p2消亡时,也会试图释放这个空间。重复释放同一块空间会产生错误。

看下面一种情况

Object p4;
p1.num = new int(1);
p4 = p1;

语句p4=p1将p1的所有变量都复制给了p4,这时,p4的num也被覆盖了,他是个指针,这个指针所指向的变量永远也找不回来了,则这块内存永远也不会被释放,成为内存垃圾。

所以重载赋值运算符给他深拷贝一下。

class Object{
public:
    int *num;
    Object(){}
    Object(const Object &other){
        if(this!=&other){
            num = new int();
            *num = *other.num;
        }
    }
    Object& operator=(const Object &other){
        if(this == &other) return *this;
        delete this->num;
        this->num = new int(*other.num);
        return *this;
    }
    ~Object(){
        if(this->num!= nullptr){
            delete this->num;
        }
    }
};

评论