实现一个依赖于姐妹班级的课程

时间:2016-05-25 20:15:28

标签: c++ oop

我有多个(比如说2个)派生自抽象基类的类,比如说Ingredient。现在,CarrotPotato通过公共继承实现Taste()的纯虚函数(称为Ingredient)。现在,假设我想要一个Salt的类Ingredient(也就是说,它是从它派生的),但需要调用其姐妹类的Taste()实现?

基本上,Salt类稍微修改了其姐妹类的Taste()实现。 这可以实施吗?如果是这样,怎么样?

这是我想要做的草图:

class Ingredient {
    virtual void Taste() = 0;
};

class Carrot : public Ingredient {
    void Taste() { printf("Tastes like carrot");}
};

class Potato : public Ingredient {
    void Taste() { printf("Tastes like potato"); }
};

class Salt : public Ingredient {
    void Taste() { SisterClass->Taste(); printf(" but salty"); }
};

2 个答案:

答案 0 :(得分:5)

盐不能合理地提供改良的味道:它需要一种实际的其他成分来加盐。但是其他哪些成分呢?事实上,具有“某种东西,但咸味”味道的不是盐,而是咸味制剂,其中包含另一种成分。这可以通过以下几种方式建模:

组合物

此准备字面上包含其他成分,并代理电话。

class SaltedPreparation : public Ingredient {
    Ingredient *baseIngredient;
    void Taste() { baseIngredient->Taste(); printf(" but salty"); }
};

Tomato tomato;
SaltedPreparation preparation;
preparation.baseIngredient = &tomato;
preparation.Taste();

继承

一个咸的番茄仍然是番茄,不是吗?这取决于与组合物相同的原理,但成分盐本身。我想。

class SaltedTomato : public Tomato {
    void Taste() { Tomato::Taste(); printf(" but salty"); }
};

SaltedTomato tomato;
tomato.Taste();

密新

每次我需要调味时,我都不热衷于编写新课程,所以让我们为此编写一个模板! Mixin模式对于现有类的这种通用修改是典型的。

template <class BaseIngredient>
class Salted : public BaseIngredient {
    void Taste() { BaseIngredient::Taste(); printf(" but salty"); }
};

Salted<Tomato> tomato;
tomato.Taste();

组合

所有上述模型都失去了盐本身也应该成为一种成分的事实。这可能没问题,但如果必须怎么办?然后复合图案可能是有用的。我们也将调味料与主要成分区分开来,因为我们不喜欢咸咸盐。

class Seasoning : public Ingredient { };

class Salt : public Seasoning {
    void Taste() { printf("salty"); }
};

class SeasonedPreparation : public Ingredient {
    Ingredient *ingredient;
    Seasoning *seasoning;
    void Taste() { ingredient->Taste(); printf(", but "); seasoning->Taste(); }
};

Tomato tomato;
Salt salt;
SeasonedPreparation preparation;
preparation.ingredient = &tomato;
preparation.seasoning = &salt;
preparation.Taste();

我现在有点饿了。

答案 1 :(得分:1)

Salt无法修改其他类的实现。但Salt可以指向另一个Ingredient的指针,例如:

class Salt : public Ingredient
{
private:
    Ingredient *OtherIngredient;
public:
    Salt(Ingredient *AOther) : OtherIngredient(AOther) {}
    virtual void Taste() { OtherIngredient->Taste(); printf(" but salty"); }
};

然后你可以这样做:

Potato potato;
Salt salt(&potato);
salt.Taste();

但这不是真的有意义,是吗?盐味道不像马铃薯,但马铃薯味道咸。所以,我可能会采取不同的方法:

#include <vector>

class Ingredient 
{
public:
    virtual void Taste() = 0;
};

class Seasoning : public Ingredient 
{
};

class SeasonableIngredient : public Ingredient 
{
protected:
    std::vector<Seasoning*> seasonings;
    virtual void TastesLike() = 0;

public:
    virtual void Taste()
    {
        printf("Tastes like ");
        TastesLike();
        if (!seasonings.empty())
        {
            std::vector<Seasoning*>::iterator iter = seasonings.begin();
            printf(" but ");
            iter->Taste();
            ++iter;
            while (iter != seasonings.end())
            {
                printf(" and ");
                iter->Taste();
                ++iter;
            }
        }
    }

    void AddSeasoning(Seasoning *seasoning) { seasonings.push_back(seasoning); }
};

class Carrot : public SeasonableIngredient
{
protected:
    virtual void TastesLike() { printf("carrot"); }
};

class Potato : public SeasonableIngredient
{
protected:
    virtual void TastesLike() { printf("potato"); }
};

class Salt : public Seasoning
{
public:
    void Taste() { printf("salty"); }
};

class Pepper : public Seasoning
{
public:
    void Taste() { printf("peppery"); }
};

Potato potato;
Salt salt;
Pepper pepper;
Potato.AddSeasoning(&salt);
Potato.AddSeasoning(&pepper);
potato.Taste();