什么是类的组合
类的组合就是以另一个的对象为数据成员,这种情况称之为类的组合
初始化参数列表优先使用组合而不是继承
组合表达式的含义一部分的关系
初始化参数列表是构造函数的另一种写法
应用场景:
形参名和数据成员相同,避免二义性问题
类和组合 必须要初始化参数列表的方式写构造
常数据成员必须采用初始化参数列表的方式
继承中子类的构造函数也必须初始化参数列表的
初始化参数列表基本形态
构造函数名(形参1,形参2....):数据成员1(形参1),数据成员2(形参2)...
#include#include using namespace std; class Student { public: //初始化参数列表 //可以避免形参名和数据成员名字相同 Student(string name, int age, int id) :name(name), age(age), id(id){} //打印 void print() { cout << name << "n" << age << "n" << id << endl; } private: string name; int age; int id; }; int main() { Student student("九梦", 20, 111); student.print(); return 0; }
領初始化参数列表其他形态
#include类的组合案例分析#include using namespace std; string name = "initName"; int returnValue() { return 21; } class Student { public: //初始化参数 Student() :name("九梦"), age(20), id(111) {} //::name标识name是全局的 Student(string name, int age, int id) :name(::name), age(returnValue()), id(id) { cout << age << endl;//就近原则 } //打印 void print() { cout << name << " " << age << " " << id << endl; } private: string name; int age; int id; }; int main() { Student student0; student0.print(); Student student("九梦", 20, 111); student.print(); return 0; }
1、类组合包含的类的对象,必须采用初始化参数列表方式调用各自类当中的构造函数去初始化 组合中初始化参数列表的写法
2、要通过包含的类的构造函数决定组合类的构造函数怎么写
构造函数名(形参1,形参2,形参3....):对象1(形参1,形参2),对象2(形参3)...
组合类注意问题
- 组合类必须要调用包含对象所属类的构造函数
- 形式上看不到包含对象所属类构造函数调用,必须准备无参的构造函数
基本组合写法
#includeusing namespace std; class Button { public: Button() { cout << "Button" << endl; } Button(int x, int y, int w, int h) :x(x), y(y), w(w), h(h) { cout << "Button" << endl; } void Draw() { cout << "按钮..." << endl; } private: int x; int y; int w; int h; }; class Edit { public: Edit() { cout << "Edit" << endl; } Edit(int x, int y) :x(x), y(y) { cout << "Edit" << endl; } void Draw() { cout << "编辑框...." << endl; } private: int x; int y; }; class Label { public: Label() { cout << "Label" << endl; } Label(int x, int y, string text) :x(x), y(y), text(text) { cout << "Label" << endl; } void Draw() { cout << "标签:" << text << endl; } private: int x; int y; string text; }; class Window { public: //window():button(),label(),edit(){} Window() //形式上没有调用,实际构造对象,必定调用包含对象的无参构造函数 { } Window(int bx, int by, int bw, int bh, int lx, int ly, string text, int ex, int ey) :button(bx, by, bw, bh),edit(ex, ey), label(lx, ly, text) { } void Show() { button.Draw(); label.Draw(); edit.Draw(); } Button getButton() { return button; } Label getLabel() { return label; } Edit getEdit() { return edit; } private: //以其他类的对象为数据成员 //构造顺序只和此处有关,和初始化参数列表顺序无关 Button button; Label label; Edit edit; }; int main() { Window object; //优先构造包含对象,在构造自身对象 //object.getButton().Draw(); //object.getEdit().Draw(); //object.getLabel().Draw(); object.Show(); Window window(10, 10, 10, 10, 20, 20, "Label", 30, 30); window.Show(); return 0; }
另一种包含指针写法
#include组合中构造和析构顺序问题using namespace std; class A { public: A(int a) :a(a) {} int geta() { return a; } private: int a; }; class B { public: B(int b) :b(b) {} int getb() { return b; } private: int b; }; class C { public: C() { pa = new A(12); pb = new B(123); } C(int a, int b) :pa(new A(a)), pb(new B(b)) {} void visitData() { cout << pa->geta() << endl; cout << pb->getb() << endl; } private: A* pa; B* pb; }; int main() { C c; c.visitData(); C value(1, 2); value.visitData(); return 0; }
一般构造顺序和析构是相反 类的组合中,优先构造包含对象,在构造自身对象 类的组合中,包含对象的构造顺序只和定义顺序有关,和初始化参数列表无关
#includethis指针using namespace std; class A { public: A() { cout << "A"; } ~A() { cout << "A" ; } }; class B { public: B() { cout << "B"; } ~B() { cout << "B"; } }; class C { public: C() { cout << "C"; } ~C() { cout << "C"; } }; class D { public: D() { cout << "D"; } ~D() { cout << "D"; } A a; B b; C c; }; int main() { { D d; } return 0; }
任何类中都存在一个this指针,this指针只允许在类中函数的函数中使用
this指针代表的是每一个对象抽象地址
基本用法
避免形参名和数据成员的名相同
#include#include using namespace std; class MM { public: MM(string name, int age); void modifyData(string name, int age) { //MM::name = name; //MM::age = age; this->name = name; this->age = age; cout << this << endl; } void print(); protected: string name; int age; }; //初始化参数列表类外也行 MM::MM(string name, int age) :name(name), age(age) { } void MM::print() { cout << this->name << "t" << this->age << endl; } int main() { MM mm("mm", 18); mm.modifyData("MM", 28); //this=&mm; cout << "&mm:" << &mm << endl; MM girl("girl", 19); girl.modifyData("girl", 29);//this=&girl; cout << "&girl:" << &girl << endl; return 0; }
其他作用
操作对象自身做一些事情
- 返回对象本身函数
- 返回对象本身的地址
#include类中类#include using namespace std; class MM { public: MM(string name, int age); void modifyData(string name, int age) { //MM::name = name; //MM::age = age; this->name = name; this->age = age; cout << this << endl; } MM& returnMM() { return *this; } MM* returnMMPoint() { return this; } void print(); protected: string name; int age; }; //初始化参数列表类外也行 MM::MM(string name, int age) :name(name), age(age) { } void MM::print() { cout << this->name << "t" << this->age << endl; } int main() { MM mm("mm", 18); mm.modifyData("MM", 28); //this=&mm; cout << "&mm:" << &mm << endl; MM girl("girl", 19); girl.modifyData("girl", 29);//this=&girl; cout << "&girl:" << &girl << endl; mm.returnMM().returnMM().returnMM().returnMM().print(); mm.returnMMPoint()->returnMMPoint()->returnMMPoint()->print(); mm.print(); mm.returnMMPoint()->print(); return 0; }
类中类就是一个类定义在另一个类当中
掌握访问类中类中即可
掌握类中的函数在类实现的写法
#includeusing namespace std; struct Node { int data; Node* next; Node() :next(nullptr) {} Node(int data) :data(data), next(nullptr) {} Node(int data, Node* next) :data(data), next(next) {} }; class List { public: List(); void insertData(int data); void printList() { Node* pmove = headNode->next; while (pmove != nullptr) { cout << pmove->data << " "; pmove = pmove->next; } cout << endl; } Node* begin() { return headNode; } private: Node* headNode; public: //类中类 class Iterator { public: Iterator(Node* pmove=nullptr); private: Node* pmove; }; }; List::List() { headNode = new Node; } void List::insertData(int data) { headNode->next = new Node(data, headNode->next); } //类中类的访问剥洋葱 List::Iterator::Iterator(Node* pmove):pmove(pmove) { } int main() { List list; List::Iterator it=list.begin(); list.insertData(1); list.insertData(2); list.insertData(3); list.printList(); return 0; }



