子对象

即用一个类的对象,充当另一个类的数据成员:

class A{...};
class B{
private:
    A a; //用类A的对象a,充当类B的数据成员
}

需要注意的是,由于类体的成员变量必须初始化,所以子对象也需要初始化。子对象的初始化方式很像常成员初始化时用到的“初始化列表”

class A{
private:
    int x;
public:
    A(){x=6;}//无参构造函数
    A(int X){x=X;}//有参构造函数
};

class B{
private:
    A a;
    int t;//拥有子对象的同时,也可以拥有其他成员变量
public:
    B(int T):a(2) { //借助有参构造函数+初始化列表
        t=T;
    }
    B(int T):a() { //借助无参构造函数+初始化列表
        t=T;
    }
    //使用无参构造函数时,必须要有a(),不可以省略
};

来一版带输出的程序,运行一下看看:

class A{
private:
    int x;
public:
    A(int X){ //有参构造函数
        x=X;
    }
    void print(){cout<<x;} //成员函数
};

class B{
private:
    A a;
public:
    B(int T):a(2){}//花括号不可以省略
    //利用有参构造函数+初始化列表
    void output(){
        a.print();
    }
};
int main(){
    B b(2);//定义对象的时候,不必考虑初始化列表
    b.output();
    return 0;
}

**ps.**初始化列表相关知识,可以类比“常成员”那一节的知识


堆对象

主要牵扯newdelete的相关知识点。
运算符new主要用于创建新的对象

  • 使用new创建一个普通类型的变量,如需初始化,直接在类型名后面加(初始值)
int *p1=new int(10);
int *p2=new int;//不需初始化则不用加()
cout<<*p1<<" "<<*p2;

输出:

10 0
  • 使用new创建一个普通类型的数组,一般不会在创建的时候直接初始化
int *arr=new int[10];

如上创建后,arr可以直接当数组名用:

arr[0]=1;
cout<<arr[0];

输出:

1

运算符delete主要用于释放对象,其作用类似于析构函数

  • 使用delete释放一个普通类型的变量
int *p=new int;
delete p;
  • 使用delete释放一个普通类型的数组
int *p=new int[10];
delete[] p;

如果能弄懂普通类型,对于“堆对象”,只需要把类名看作“普通类型名”即可

class A{
private:
    int x;
public:
    A(){x=0;}
    A(int X){x=X;}
};
int main(){
    A *p1=new A;//利用无参构造函数定义堆对象
    A *p2=new A(2);//利用有参构造函数定义堆对象
    A *arr=new A[6];//利用无参构造函数定义堆对象数组
    delete p1;//释放p1
    delete p2;//释放p2
    delete [] arr;//释放arr
    return 0;
}