1.类的组合
当我们想在一个类中把另一个类的对象当作成员数据时,我们就需要用到类的组合了。而数据成员是其他类的对象的类,我们称之为组合类。
注:能用类的组合,我们尽量不用继承
在使用类的组合的时候,我们要注意组合类的构造函数的写法。成员数据中的对象必须通过初始化参数列表的方式来赋初始值(调用该对象的类的构造函数),其他的成员数据没有硬性规定。
class MM{
public:
MM(string MMname,int MMage):MMname(MMname),(MMage)MMage {}
protected:
string MMname;
int MMage;
};
class GG{
public:
//使用初始化列表,并且调用对象对应的构造函数
MM(string MMname,int MMage,string GGname,int GGage):mm(MMname,MMage),GGname(GGname),GGage(GGage) {}
protected:
MM mm;
string GGname;
int GGage;
};
当数据成员是对象的时候,只能定义一个对象,不能直接构造一个对象。
MM mm; //正确
MM mm("xx",20); //错误,不能直接构造对象,没有这种写法
组合类中的对象对于他自己来说是属于类外的,所以它依然受权限限定。只能通过对象访问公有属性。想要访问boy中的保护属性,可以通过在Boy类中设置接口来让boy调用。
class Boy
{
public:
Boy(string name, int age) :name(name), age(age) {}
//公有属性 可以被boy直接调用
void print()
{
cout << name << "\t" << age << endl;
}
protected:
//保护属性 类外无法直接调用
void printData()
{
cout << name << "\t" << age << endl;
}
string name;
int age;
};
class MM
{
public:
MM(string boyName, int boyAge, string mmName) :boy(boyName, boyAge)
{
this->mmName = mmName;
}
void print()
{
//通过Boy中的接口来调用输出boy对象中的数据成员
boy.print();
//boy.printData(); 不可访问,boy对于Boy是类外,不可直接访问保护属性
cout << mmName << endl;
}
protected:
string mmName;
Boy boy;
};
(2)组合类中对象的构造顺序(小知识)
类的组合的构造顺序问题:组合类的构造顺序只和成员数据中对象定义的顺序有关,和初始化参数列表中的参数顺序无关。
假设:若有A B C 三个类,现定义一个D类,想要在D类的成员数据中定义A B C类的对象。
A a; B b; C c;这时候构造顺序就是你定义的顺序,无论你的初始化参数列表把谁写在前面,构造顺序都是按照 a--->b--->c--->的顺序去构造。
2.类中类
类中类,即在类中定义另一个类。(类中类仍然受类的权限限定),访问方式,需要类名限定。
class A{
public:
class B{
public:
protected:
string nameB;
};
protected:
string nameA;
};
int main(){
A::B b;
return 0;
}
通过类名限定来定义类中类的对象,但是必须是在public 属性下的类中类。不然没办法类名限定访问(还是那句话,类中类仍然受权限限定)。
3.类中的默认函数
-
默认构造函数
-
默认拷贝构造函数
-
默认析构函数
-
默认赋值运算
-
class A { public: A() = default; A(A& object) = default; //void print() = default; A& operator=(A& object) = default; ~A() = default; };
使用=defaul就能使用类中的默认函数。