类与类之间的关系
复合关系、委托关系、继承关系。
1.复合关系,表示has-a,也就是一个类中包含有另外一个类,通过成员对象的形式表现。
2.委托关系,一个类当中有另外一个类的指针成员。
复合和委托中,内部的对象的生命周期是不同步的。复合中,内部是对象和外部的对象是一致的,而委托中,内部是对象是一个指针,只有当需要时才让其指向某个对象。
3.继承关系,一个类通过语句 : public CBase,继承类中的数据和函数。
继承过程中的构造函数
当类与类之间存在继承关系,子类继承父类,则子类中拥有父类的一部分。子类对象创建时,则先调用父类的构造函数,若父类的构造函数有带参数,则需要显示的调用父类带参数的构造函数,然后再调用子类的构造函数。
复合和继承
如果一个类中既有继承、又有委托,那么这个类在实例化一个对象时。先是调用父类的构造函数,再调用复合类的构造函数,最后再调用自己的构造函数。而析构函数的调用过程刚好相反。
子类继承父类,父类的数据继承下来,在子类中占据内存空间,而父类的函数 继承的是调用权,不占据内存空间。
父类的析构函数
如果一个类要作为父类使用,那么他的析构函数必须是virtual。
虚函数,继承与虚函数的组合
在设计一个类时,如果考虑到继承关系,且作为一个父类,在设计成员函数时,有三种选择:非虚函数、虚函数、纯虚函数:
1.非虚函数:不希望子类重新定义。
2.虚函数:希望子类重新进行定义,覆盖父类的一模一样的函数,但是子类可以选择不重新定义。
3.纯虚函数:子类一定要重新定义,因为父类没有进行定义。
设计模式:
Delegation(委托)+Inheritance(集成)
以不同的obsever观察父类的数据。
subject类和observer是委托的关系,Subject类中可以使用vector容器,容器容纳的是observer的指针。子类继承自observer,所以子类其实是observer的一种,子类再覆盖掉父类的update函数。那么所以子类对象被创建后,都被放入到subject类的m_views容器中,当调用起notify函数时,容器中的子类,也就会调用起自己的update函数。
Composite设计模式
Primitive类和Composite类均是Component类的子类,子类Composite中有一个容器,可容纳Component类的指针,所以子类也可以放入到这个容器中。子类Composite中又覆盖了父类的add函数,那么子类对象创建时,调用的add函数,其实调用的是子类Composite中的add函数,那么2个子类均被放入同一个容器中,后面的操作就很自由了。
Prototype设计模式
父类早已写好,但子类以后才会创建,创建后要被父类知道。那么子类在创建时,必须有一定的限制,如定义一个静态的对象和一个无参数构造函数,并写在private中。同时,该构造函数调用父类的addPrototype函数,把子类对象add到父类的数组中,让父类知道。
子类均覆盖父类的clone函数,当要使用子类时,先调用父类的findAndClone函数,该函数中又调用clone函数,该函数已被覆盖,调用的其实是子类的clone函数。子类的clone函数又new 出了一个自己,并返回,new的时候带了一个参数,否则又循环调用起无参数构造函数。调用子类的clone函数后得到的是子类的指针,此时就可以对子类进行操作了。
补充 vector相关:
vector:
定义
vector 向量:一种对象实体, 能够容纳许多其他类型相同的元素, 因此又被称为容器。
使用时应包含 #include<vector>
vector 容器与数组相比其优点在于它能够根据需要随时自动调整自身的大小以便容下所要放入的元素,以及提供较多操作方法。
向量的声明及初始化
vector 型变量的声明以及初始化的形式也有许多, 常用的有以下几种形式:
vector<int> a ; //声明一个int型向量a
vector<int> a(10) ; //声明一个初始大小为10的向量
vector<int> a(10, 1) ; //声明一个初始大小为10且初始值都为1的向量
vector<int> b(a) ; //声明并用向量a初始化向量b
vector<int> b(a.begin(), a.begin()+3) ; //将a向量中从第0个到第2个(共3个)作为向量b的初始值
使用数组来初始化向量:
int n[] = {1, 2, 3, 4, 5} ;
vector<int> a(n, n+5) ; //将数组n的前5个元素作为向量a的初值
vector<int> a(&n[1], &n[4]) ; //将n[1] - n[4]范围内的元素作为向量a的初值
元素的输入及访问
- 用cin>>进行输入, cout<<a[n]这样进行输出。
2.使用遍历器(又称迭代器)进行输出控制。在 vector<int> b(a.begin(), a.begin()+3) ; 向量元素的位置便成为遍历器, 同时, 向量元素的位置也是一种数据类型, 在向量中遍历器的类型为: vector<int>::iterator。 遍历器不但表示元素位置, 还可以再容器中前后移动。
//全部输出
vector<int>::iterator t ;
for(t=a.begin(); t!=a.end(); t++)
cout<<*t<<" " ;
基本操作
1>. a.size() //获取向量中的元素个数
2>. a.empty() //判断向量是否为空
3>. a.clear() //清空向量中的元素
4>. 复制
a = b ; //将b向量复制到a向量中
5>. 比较
保持 ==、!=、>、>=、<、<= 的惯有含义 ;
如: a == b ; //a向量与b向量比较, 相等则返回1
6>. 插入 - insert
a.insert(a.begin(), 1000); //将1000插入到向量a的起始位置前
a.insert(a.begin(), 3, 1000) ; //将1000分别插入到向量元素位置的0-2处(共3个元素)
vector<int> a(5, 1) ;
vector<int> b(10) ;
b.insert(b.begin(), a.begin(), a.end()) ; //将a.begin(), a.end()之间的全部元素插入到b.begin()前
7>. 删除 - erase
b.erase(b.begin()) ; //将起始位置的元素删除
b.erase(b.begin(), b.begin()+3) ; //将(b.begin(), b.begin()+3)之间的元素删除
8>. 交换 - swap
b.swap(a) ; //a向量与b向量进行交换
网友评论