0
点赞
收藏
分享

微信扫一扫

第十六讲 三大面向对象关系(复合、委托、继承)—————面向对象高级开发

1 三大面向对象关系(复合、委托、继承)

1.1 composition(复合)

关系:has-a
第十六讲 三大面向对象关系(复合、委托、继承)—————面向对象高级开发_#include

  • 1,构造关系:由内到外
  • 2,析构关系:由外到内
    例如:

#include 

class Son{
public:
Son(){std::cout<<"Son construction"<<std::endl;}
~Son(){std::cout<<"Son destroy"<<std::endl;}
};

class Mother{
public:
Mother(){std::cout<<"Mother construction"<<std::endl;}
~Mother(){std::cout<<"Mother destroy"<<std::endl;}
private:
Son son;
};

int main(){
Mother mother;
return 0;
}

输出:

Son construction
Mother construction
Mother destroy
Son destroy

1.2 Delegation(委托)【composition by reference】

一种通过引用的特殊的复合
第十六讲 三大面向对象关系(复合、委托、继承)—————面向对象高级开发_ios_02
Pimpl(pointer to implementation):母类只是对外的接口,真正的实现都在子类里,当母类需要动作的时候,就去调用子类。

作用:母类有一个指针去指向实现所有功能的子类,这种手法的好处在于,这个指针还可以去指向不同的实现类,去实现不同的功能,子类不管怎么变动都不影响s母类也就不影响客户端,母类也永远不用再编译。

示例:

#include 

class Mother;
class Son{//真正的实现
friend class Mother;
public:
Son(int data = 0):m_data(data){std::cout<<"Son construction"<<std::endl;}
~Son(){std::cout<<"Son destroy"<<std::endl;}
private:
int m_data;
void setData(int data){m_data = data;}
void printData()const {std::cout<<"data:"<<m_data<<std::endl;}
};

class Mother{//对外接口
public:
Mother(){std::cout<<"Mother construction"<<std::endl;}
~Mother(){std::cout<<"Mother destroy"<<std::endl;}
void printData(){son->printData();}
void setData(int data){son->setData(data);}
private:
Son* son;//Pimpl(pointer to implementation)
};

int main(){
Mother mother;
mother.setData(2);
mother.printData();
return 0;
}

输出:

Mother construction
data:2
Mother destroy

1.3 Inheritance(继承)

表示:is-a
第十六讲 三大面向对象关系(复合、委托、继承)—————面向对象高级开发_ios_03
调用函数时,是在运行时决定,而不是在编译期间决定。

公有继承:所有公有成员和保护成员保持原装
私有继承:所有公有成员和保护成员都成为派生类的私有成员
保护继承:所有公有成员和保护成员都成为派生类的保护成员

1.3.1 成员函数类型

  • 1,non-virtual函数:不希望被derived(派生类)override(重新定义); 【void fun();】
  • 2,virtual函数:希望被derived类重新定义,且已有默认值;【virtual void fun();】
  • 3,pure函数:一定要重新定义【virtual void fun() = 0;】

1.3.2 使用条件以及示例

条件:

  • 1,函数时虚函数,声明时用virtual修饰;
  • 2,使用指针或引用调用;
  • 3,指针或引用的对象必须是基类。

纯函数: 函数变量列表后加 ​​= 0​​ 声明了纯虚函数的类,不能实例化为对象。必须要实现后,才能实例化。

构造顺序:基类---->派生类
析构顺序:派生类—>基类

范例:

#include 

class Base{
protected:
//纯虚函数:无法实例化
virtual void printData()const = 0;
};

class Father:public Base{//对外接口
public:
Father(int data = 0):m_data(data){std::cout<<"Father construction"<<std::endl;}
virtual ~Father(){std::cout<<"Father destroy"<<std::endl;}
virtual void print(){std::cout<<"Father print()"<<std::endl;}
protected://仅继承可以访问
virtual void printData()const{std::cout<<"Father:"<<m_data<<std::endl;};//纯虚函数

private:
int m_data;
};

class Son: public Father{//真正的实现
public:
Son(int data = 0):m_data(data){std::cout<<"Son construction"<<std::endl;}
~Son(){std::cout<<"Son destroy"<<std::endl;}
void setData(){printData();}
void print(){std::cout<<"Son print()"<<std::endl;}
private:
int m_data;
};

int main(){
Father father;
Son son;
father.print();
son.print();
//动态绑定
std::cout<<"动态绑定------------->"<<std::endl;
Father* fatherP = &father;
Father& sonP = son;
fatherP->print();
sonP.print();
//显示调用
std::cout<<"显示调用------------->"<<std::endl;
sonP.Father::print();

return 0;
}

输出:

Father construction
Father construction
Son construction
Father print()
Son print()
动态绑定------------->
Father print()
Son print()
显示调用------------->
Father print()
Son destroy
Father destroy
Father destroy

1.3.3 template Mothod设计模式【模板方法模式】

作用:在父类中定义处理流程的框架,在子类中实现具体处理。
MFC中经常用到此方法。

#include 
using std::cout;

class Base{
private:
virtual void calculate() = 0;
public:
void getResult(){
std::cout<<"satrt:"<<std::endl;
calculate();//具体实现放在子类
std::cout<<"end";
}
};

class Derived: public Base{
public:
virtual void calculate(){
std::cout<<"calculate"<<std::endl;
}
};

int main( ){
Derived derive;
derive.getResult();
return 0;
}

输出:

satrt:
calculate
end

1.4 继承+复合

第十六讲 三大面向对象关系(复合、委托、继承)—————面向对象高级开发_#include_04

构造顺序:A—>C—>B
析构顺序:B—>C—>A

//计算复合、继承的构造函数先后
#include
using std::cout;
using std::endl;

class A{
public:
A(){cout<<"构造A "<<endl;}
~A(){cout<<"析构A "<<endl;}
};

class C{
public:
C(){cout<<"构造C "<<endl;}
~C(){cout<<"析构C "<<endl;}
};

class B :public A{
public:
B(){cout<<"构造B "<<endl;}
~B(){cout<<"析构B "<<endl;}
private:
C c;
};



int main( ){
B b;
return 0;
}

输出:

构造A 
构造C
构造B
析构B
析构C
析构A

1.5 继承 + 委托

1.5.1 案列

解决的问题:一个文件,四个窗口,当文件变化时,窗口也会跟着改变。
第十六讲 三大面向对象关系(复合、委托、继承)—————面向对象高级开发_#include_05
第十六讲 三大面向对象关系(复合、委托、继承)—————面向对象高级开发_ios_06设计方法:
第十六讲 三大面向对象关系(复合、委托、继承)—————面向对象高级开发_ios_07

#include 
#include
//前置声明
class Observer;
//数据
class Subject{
private:
int m_value;
std::vector<Observer*> m_views;
public:
void attach(Observer* objs){
m_views.push_back(objs);
}
void setVal(int value){
m_value = value;
notify();
}
//直接在类内定义会报错:error: member access into incomplete type
void notify();
};

//视图
class Observer{
public:
virtual void update(Subject* subject, int value) = 0;
};

void Subject::notify() {
for(int i = 0;i < m_views.size();++i){
m_views[i]->update(this, m_value);
}
}

int main( ){

return 0;
}

1.5.2 Composite设计模式【部分整体模式】

解决问题:文件系统,里面有文件夹或文件

案例:
第十六讲 三大面向对象关系(复合、委托、继承)—————面向对象高级开发_ios_08

//文件系统

#include 
#include
class Component{
public:
Component(int data):m_data(data){}
virtual void add(Component*){}
private:
int m_data;
};
//文件
class Primitive:public Component{
public:
Primitive(int data):Component(data){}
};
//文件夹
class Composite:public Component{
public:
Composite(int data):Component(data){}
void add(Component* elem){m_p.push_back(elem);}
private:
std::vector<Component*> m_p;

};

int main( ){

return 0;
}

1.5.3 Prototype设计模式【原型模式】

作用:用于创建重复的对象,同时又能保证性能。

解决问题:创建未来才会出现的子类,让子类自己创建自己(原型),然后基类可以看见原型并复制它。

案例:
第十六讲 三大面向对象关系(复合、委托、继承)—————面向对象高级开发_C++_09

#include 
#include

enum imageType{
LSAT,SPOT
};

class Image{
public:
//发现和复制
static Image* findAndClone(imageType);
virtual void draw() = 0;
static void printNextSlot(){std::cout<<"m_nextSlot:"<<m_nextSlot<<std::endl;}
virtual imageType returnType() = 0;
protected:
//用于子类返回类型
// virtual imageType returnType() = 0;
//用于子类创建自己的原型
virtual Image* clone() = 0;
//添加原型
static void addProtoType(Image* image){
m_protoTypes[m_nextSlot++] = image;
}
private:
static int m_nextSlot;
static Image* m_protoTypes[10];
};

Image* Image::m_protoTypes[];
int Image::m_nextSlot;

class LandSatImage: public Image{
public:
imageType returnType(){
return LSAT;
}
void draw(){
std::cout<<"LandSatImage::draw:"<<m_id<<std::endl;
}
//调用带参构造
Image* clone(){
return new LandSatImage(1);
}
protected:
//避免addProtoType重复添加自己
//只用于基类中的clone函数
LandSatImage(int dummy){
m_id = m_cout++;
}

private:
int m_id;
static int m_cout;
static LandSatImage m_landSatImage;
//调用静态的自己
//默认构造
LandSatImage(){
std::cout<<"构造LandSatImage"<<std::endl;
addProtoType(this);
}
};
LandSatImage LandSatImage::m_landSatImage;
int LandSatImage::m_cout;

class SpotImage: public Image{
public:
imageType returnType(){return SPOT;}
Image* clone(){ return new SpotImage(1);}
void draw(){std::cout<<"SpotImage:draw:"<<m_id<<std::endl;}

protected:
SpotImage(int dummy){
m_id = m_cout++;
}
private:
int m_id;
static int m_cout;
static SpotImage m_spotImage;
SpotImage(){
std::cout<<"构造SpotImage"<<std::endl;
addProtoType(this);
}
};
SpotImage SpotImage::m_spotImage;
int SpotImage::m_cout;


Image* Image::findAndClone(imageType type) {
for(int i = 0;i < m_nextSlot;++i)
if(m_protoTypes[i]->returnType() == type)
return m_protoTypes[i]->clone();
}

int main( ){
Image* landSatImage = Image::findAndClone(LSAT);
Image* spotImage = Image::findAndClone(SPOT);
Image::printNextSlot();
std::cout<<"type:"<<spotImage->returnType()<<std::endl;
return 0;
}

举报

相关推荐

0 条评论