一、以另一个类的对象作为一个类的数据成员
1.构造函数的写法必须采用初始化参数列表的写法
注意点:①当B类含有数据成员A a;时,此时的a是不能直接初始化的。
②一般在B的构造函数参数中,先写类组合的参数,且在初始化参数列表中用的是调用A的初始化成员列表(A的构造函数的方式)
③权限问题:B类中的a对象相对于A类是属于类外的,仅能通过“提供一个接口”去访问protected中的数据成员(函数),但是B类访问自己是不受限制的(如下面B类中的print()函数,通过A类中写好的接口去访问a的数据成员)
#include<iostream>
using namespace std;
class A
{
public:
A(int id,string name):id(id),name(name) {}
void print()
{
cout <<id <<"\t"<<name << endl;
}
protected:
int id;
string name;
};
class B
{
public:
B(string Aname,int Aid,int Bnum):a(Aid,Aname),num(Bnum){}
void print()
{
a.print();
cout << num << endl;
}
protected:
A a;
int num;
};
int main()
{
B b("wbm", 002, 19);
b.print();
return 0;
}
2.类的组合构造顺序:
#include<iostream>
using namespace std;
class A
{
public:
A(int num):num(num)
{
cout << "A" ;
}
int num;
};
class B
{
public:
B(int num):num(num)
{
cout << "B";
}
int num;
};
class C
{
public:
C(int num):num(num)
{
cout << "C";
}
int num;
};
class D
{
public:
D(int num, int anum, int bnum, int cnum) :num(num), a(anum), b(bnum), c(cnum)
{
cout << "D";
}
protected:
A a;
B b;
C c;
int num;
};
int main()
{
D(1, 2, 3, 4);//输出 ABCD 析构函数顺序和他相反
return 0;
}
总结:构造函数顺序仅和在D类中定义的几个数据成员的顺序有关->析构顺序相反
二、类中类
1.类中的类仍然是要收到权限限定的,且访问的方式需要进行类名限定::。
实例:迭代器iterator-->类模仿指针行为(包含指针的前插、打印等以及运算符的重载)
#include<iostream>
using namespace std;
struct Node
{
int data;
Node* next;
Node()
{
this->next = nullptr;//创建一个表头
}
Node(int data)//新建一个节点
{
this->next = nullptr;
this->data = data;//相当于初始化
}
};
class List//链表
{
public:
List()
{
headNode = new Node;//调用的struct Node里面的不含参数的初始化——>也就是给了一个nullptr方便后面终止
}
void push_front(int data)前插法(头节点始终不变,永远在头节点后面插入一个)
{
Node* newNode = new Node(data);
newNode->next = headNode->next;
headNode->next = newNode;
}
protected:
Node* headNode;
public:
//迭代器->类模仿指针行为
class iterator
{
public:
iterator(Node* pMove = nullptr) :pMove(pMove) {}
void operator=(Node* pMove)//重载=
{
this->pMove = pMove;
}
bool operator!=(Node* pMove)
{
return this->pMove != pMove;
}
iterator operator++()//重载前置++
{
pMove = pMove->next;//让指针自己移动,切不可新建一个不知道的节点打断整个链表
return iterator(pMove);
}
Node* &operator*()
{
return pMove;
}
protected:
Node* pMove;
};
Node* begin()//作为遍历的起点,head->next作为起点,不要headNode
{
return headNode->next;
}
Node* end()
{
return nullptr;
}
};
int main()
{
List list;
for (int i = 0; i < 3; i++)
{
list.push_front(i);
}
List::iterator iter;//相当于一个指针
for (iter = list.begin(); iter != list.end(); ++iter)
{
cout << (*iter)->data;//强烈注意,这边对iter进行解引用后仍然是一个指针。
}
return 0;
}
补充:类中对枚举类型的访问方式
也受权限限定,也需要类名限定::
#include<iostream>
using namespace std;
class A
{
public:
enum week{mon,tus,thus};
private:
enum time{fisrt,second};
};
int main()
{
A a;
cout << A::week::mon;
//cout << A::time;//不可以访问
return 0;
}
三、类中默认的的函数
大致上是四个
#include<iostream>
using namespace std;
class A
{
public:
A() = default;//默认的构造函数
A(A& object) = default;//默认的拷贝函数
A& operator=(const A& a) = default;//默认的重载=
~A() = default;//默认的析构函数
protected:
int num;
};
int main()
{
A wbm;
A jie(wbm);
wbm = jie;
return 0;
}