通过这个例子发现对面向对象的继承还是没有理解到位,还需努力。
#include<iostream>
#include<string>
using namespace std;
const int ESPRESSO_PRICE=25;
const int DARKROAST_PRICE=20;
const int MOCHA_PRICE=10;
const int WHIP_PRICE=8;
class Beverage{
protected:
string description;
public:
virtual string getDescription(){return description;}
virtual int cost()=0;
};
class CondimentDecorator:public Beverage{//配料
protected:
Beverage* beverage;
public:
};
class Espresso:public Beverage{ //蒸馏咖啡
public:
Espresso(){description="Espresson";}
int cost(){return ESPRESSO_PRICE;}
};
class DarkRoast:public Beverage{//深度烘焙咖啡
public:
DarkRoast(){cout<<"DarkRoast的构造函数\n";description="DarkRoast";}
int cost(){cout<<"DarkRoast的cost\n";return DARKROAST_PRICE;}
};
class Mocha:public CondimentDecorator{//摩卡
public:
Mocha(){}
Mocha(Beverage* beverage){this->beverage=beverage;}
string getDescription(){cout<<"Mocha的getdec\n";return beverage->getDescription()+",Mocha";}
int cost(){cout<<"Mocha的cost\n";return MOCHA_PRICE+beverage->cost();}
};
class Whip:public CondimentDecorator{//奶泡
public:
Whip(){}
Whip(Beverage* beverage){this->beverage=beverage;}
string getDescription(){cout<<"Whip的getdec\n";return beverage->getDescription()+",Whip";}
int cost(){cout<<"Whip的cost\n";return WHIP_PRICE+beverage->cost();}
};
int main()
{
Beverage* bg=new DarkRoast();
bg=new Mocha(bg);
bg=new Whip(bg);
cout<<bg->getDescription()<<"¥"<<bg->cost()<<endl;
return 0;
}
刚开始看到这个程序的时候,不太理解为什么输出是DarkRoast,Mocha,Whip¥38。感觉Mocha和Whip两个子类里的this->beverage改变的明明都是DarkRoast的beverage,结果却能起到Whip-Mocha-DarkRoast层层向上的作用。
后来经过测试才发现,Mocha和Whip继承了DarkRoast之后,每个子类会单独拥有一个beverage属性。
当父类指针指向子类的对象时,这个子类的beverage才是和DarkRoast的beverage关联的,因为主函数里自始至终只用了一个Beverage*的指针
这里先把总结写下来,再做下面的讨论:
在只用一个父类指针指向不同对象的情况下。
(1)对于从父类继承而来,子类中没有另外声明的属性x,子类对象之间没有影响(可以赋不同值)。
(2)同一时间,只有一个子类对象的属性x的改变会影响父类对象的属性(因为只有一个父类指针)
接下里逐步考虑主函数里的语句做了什么:
(0)首先明确一点是,只有CondimentDecorator里声明了Beverage* beverage,其余类只是使用。
(1)执行Beverage* bg=new DarkRoast();时,bg指向DarkkRoast的对象。
(2)执行bg=new Mocha(bg)时,根据Mocha类的自定义构造函数,把Mocha对象中的beverage指向DarkRoast(此时在Mocha类中beverage->getDescription()就会去执行DarkRoast的getDescription方法),此时父类CondimentDecorator对象里的beverage也同样指向了DarkRoast,此时这两个是关联的。这条语句执行完之后,bg就指向了Mocha。
(3)执行bg=new Whip(bg)时,把Whip对象中的beverage指向了Mocha,但要注意的是,此时Mocha对象中的beverage没有改变!!只是CondimentDecorator对象“跟随”Whip对象里的beverage一起指向了Mocha。执行完之后,bg指向Whip
(4)bg->getDescription()时,因为bg指向Whip,先执行Whip的getDescription(),由于该方法返回的是beverage->getDescription()+",Whip",而此时Whip对象的beverage指向的是Mocha,所以就又会去调用Mocha的getDescription()方法,如此就得到了上面的输出。
下面附上一个可以检验结果的例子
#include<iostream>
#include <typeinfo>
#include<string>
using namespace std;
const int ESPRESSO_PRICE=25;
const int DARKROAST_PRICE=20;
const int MOCHA_PRICE=10;
const int WHIP_PRICE=8;
class A{
protected:
int num;
public:
virtual void setV(int b){
num=b;
}
virtual void pt(){
cout<<"我是A:"<<num<<endl;
}
void testA(){
cout<<"我是A的test:"<<num<<endl;
}
void setA(int v){
num=v;
}
};
class B:public A{
public:
void setV(int c){
this->num=c*2;
}
void pt(){
cout<<"我是B:"<<num<<endl;
}
void testB(){
cout<<"我是B的test:"<<num<<endl;
}
};
class C:public A{
public:
void setV(int d){
this->num=d*3;
}
void pt(){
cout<<"我是C:"<<num<<endl;
}
void testC(){
cout<<"我是C的test:"<<num<<endl;
}
};
int main()
{
A* a=new A();
B* b=new B();
C* c=new C();
//把a指向b,赋值后只有a,b有值且相等,c仍然是脏数据
a=b;
a->setV(5);
cout<<"a指向b"<<endl;
a->testA();
b->testB();
c->testC();
cout<<"\n\n";
//把a指向c,赋值后,a值随着c而改变,b值不变
a=c;
a->setV(5);
cout<<"a指向c"<<endl;
a->testA();
b->testB();
c->testC();
cout<<"\n\n";
//调用a的方法对a赋值,赋值后,c值随着a而改变,b值不变
a->setA(2);
a->testA();
b->testB();
c->testC();
cout<<"\n\n";
return 0;
}