C++ 子类化和添加数据成员

C++ 子类化和添加数据成员,c++,class,C++,Class,我有一个类的层次结构,如下所示: class Critical { public: Critical(int a, int b) : m_a(a), m_b(b) { } virtual ~Critical() { } int GetA() { return m_a; } int GetB() { return m_b; } void SetA(int a) { m_a = a; }

我有一个类的层次结构,如下所示:


    class Critical
    {
    public:
        Critical(int a, int b) : m_a(a), m_b(b) { }
        virtual ~Critical() { }
        int GetA() { return m_a; }
        int GetB() { return m_b; }
        void SetA(int a) { m_a = a; }
        void SetB(int b) { m_b = b; }
    protected:
        int m_a;
        int m_b;
    };

    class CriticalFlavor : public Critical
    {
    public:
        CriticalFlavor(int a, int b, int flavor) : Critical(a, b), m_flavor(flavor) { }
        virtual ~CriticalFlavor() { }
        int GetFlavor() { return m_flavor; }
        void SetFlavor(int flavor) { m_flavor = flavor; }
    protected:
        int m_flavor;
    };

    class CriticalTwist : public Critical
    {
    public:
        CriticalTwist(int a, int b, int twist) : Critical(a, b), m_twist(twist) { }
        virtual ~CriticalTwist() { }
        int GetTwist() { return m_twist; }
        void SetTwist(int twist) { m_twist = twist; }
    protected:
        int m_twist;
    };

    class Critical
    {
    public:
        virtual int GetA() = 0;
        virtual int GetB() = 0;
        virtual void SetA(int a) = 0;
        virtual void SetB(int b) = 0;
    };

    class CriticalImpl : public Critical
    {
    public:
        CriticalImpl(int a, int b) : m_a(a), m_b(b) { }
        ~CriticalImpl() { }
        int GetA() { return m_a; }
        int GetB() { return m_b; }
        void SetA(int a) { m_a = a; }
        void SetB(int b) { m_b = b; }
    private:
        int m_a;
        int m_b;
    };

    class CriticalFlavor
    {
    public:
        virtual int GetFlavor() = 0;
        virtual void SetFlavor(int flavor) = 0;
    };

    class CriticalFlavorImpl : public Critical, public CriticalFlavor
    {
    public:
        CriticalFlavorImpl(int a, int b, int flavor) : m_flavor(flavor), m_critical(new CriticalImpl(a, b)) { }
        ~CriticalFlavorImpl() { delete m_critical; }
        int GetFlavor() { return m_flavor; }
        void SetFlavor(int flavor) { m_flavor = flavor; }
 int GetA() { return m_critical->GetA(); }
        int GetB() { return m_critical->GetB(); }
        void SetA(int a) { m_critical->SetA(a); }
        void SetB(int b) { m_critical->SetB(b); }
    private:
        int m_flavor;
 CriticalImpl* m_critical;
    };

从设计角度来看,上述内容对我来说并不合适,最让我困扰的是 添加成员变量似乎可以驱动这些类的接口 (执行上述操作的真正代码稍微复杂一些,但仍然采用相同的模式)。 当需要另一个“关键”类时,这种情况就会激增,而这个类只是添加了一些其他的属性 财产。 你觉得这样对吗?我如何重构这样的代码? 一个想法是只拥有一组接口,并在涉及基本对象时使用组合 例如:


    class Critical
    {
    public:
        Critical(int a, int b) : m_a(a), m_b(b) { }
        virtual ~Critical() { }
        int GetA() { return m_a; }
        int GetB() { return m_b; }
        void SetA(int a) { m_a = a; }
        void SetB(int b) { m_b = b; }
    protected:
        int m_a;
        int m_b;
    };

    class CriticalFlavor : public Critical
    {
    public:
        CriticalFlavor(int a, int b, int flavor) : Critical(a, b), m_flavor(flavor) { }
        virtual ~CriticalFlavor() { }
        int GetFlavor() { return m_flavor; }
        void SetFlavor(int flavor) { m_flavor = flavor; }
    protected:
        int m_flavor;
    };

    class CriticalTwist : public Critical
    {
    public:
        CriticalTwist(int a, int b, int twist) : Critical(a, b), m_twist(twist) { }
        virtual ~CriticalTwist() { }
        int GetTwist() { return m_twist; }
        void SetTwist(int twist) { m_twist = twist; }
    protected:
        int m_twist;
    };

    class Critical
    {
    public:
        virtual int GetA() = 0;
        virtual int GetB() = 0;
        virtual void SetA(int a) = 0;
        virtual void SetB(int b) = 0;
    };

    class CriticalImpl : public Critical
    {
    public:
        CriticalImpl(int a, int b) : m_a(a), m_b(b) { }
        ~CriticalImpl() { }
        int GetA() { return m_a; }
        int GetB() { return m_b; }
        void SetA(int a) { m_a = a; }
        void SetB(int b) { m_b = b; }
    private:
        int m_a;
        int m_b;
    };

    class CriticalFlavor
    {
    public:
        virtual int GetFlavor() = 0;
        virtual void SetFlavor(int flavor) = 0;
    };

    class CriticalFlavorImpl : public Critical, public CriticalFlavor
    {
    public:
        CriticalFlavorImpl(int a, int b, int flavor) : m_flavor(flavor), m_critical(new CriticalImpl(a, b)) { }
        ~CriticalFlavorImpl() { delete m_critical; }
        int GetFlavor() { return m_flavor; }
        void SetFlavor(int flavor) { m_flavor = flavor; }
 int GetA() { return m_critical->GetA(); }
        int GetB() { return m_critical->GetB(); }
        void SetA(int a) { m_critical->SetA(a); }
        void SetB(int b) { m_critical->SetB(b); }
    private:
        int m_flavor;
 CriticalImpl* m_critical;
    };


在这里很难说继承是否是正确的想法,而不了解更多关于真实代码的信息。你想要多态性吗(如果是CriticalFlavor、CriticalTwist或CriticalWhatch,那么对一个临界点进行操作并获得不同的效果)?A和B的结构顺序和其他东西重要吗?您是否计划有一个更复杂的类树,包含CriticalFlavorTemperature和CriticalTwistColor之类的内容

也就是说,对于合成方法,我可能会这样做:

class Critical
{
public:
    Critical(int a, int b) : m_a(a), m_b(b) { }
    ~Critical() { }
    int GetA() const { return m_a; }
    int GetB() const { return m_b; }
    void SetA(int a) { m_a = a; }
    void SetB(int b) { m_b = b; }
private:
    int m_a;
    int m_b;
};

class CriticalFlavor
{
public:
    CriticalFlavor(int a, int b, int flavor) : m_flavor(flavor), m_critical(a, b) { }
    ~CriticalFlavor() {}
    int GetFlavor() const { return m_flavor; }
    void SetFlavor(int flavor) { m_flavor = flavor; }
    int GetA() const { return m_critical.GetA(); }
    int GetB() const { return m_critical.GetB(); }
    void SetA(int a) { m_critical.SetA(a); }
    void SetB(int b) { m_critical.GetB(b); }
private:
    int m_flavor;
    Critical m_critical;
};

@马吕斯从你的帖子中我所能理解的是,你想将数据访问与实际数据结构分开

class Critical
{
public:
    virtual int GetA() = 0;
    virtual int GetB() = 0;
    virtual void SetA(int a) = 0;
    virtual void SetB(int b) = 0;
};

class Flavor
{
public:
    virtual int GetFlavor() = 0;
    virtual void SetFlavor(int a) = 0;
};

template<class T>
class AccessCritical : public Critical
{
public:
    AccessCritical(T &ref) : data(ref) {}

    int GetA() { return (data.m_a); }
    int GetB() { return (data.m_b); }
    void SetA(int a) { data.m_a = a; }
    void SetB(int b) { data.m_b = b; }
private:
    T &data;
};

template<class T>
class AccessFlavor : public Flavor
{
public:
    AccessFlavor(T &ref) : data(ref) {}
    int GetFlavor() { return (data.m_flavor); }
    void SetFlavor(int flavor) { data.m_flavor = flavor; }
private:
    T &data;
};

struct MyStructA {
    int m_a, m_b;

    AccessCritical<MyStructA> critical;
    MyStructA() : critical(*this) {}
};

struct MyStructB {
    int m_flavor;

    AccessFlavor<MyStructB> flavor;
    MyStructB() : flavor(*this) {}
};

struct MyStructC {
    int m_a, m_b;
    int m_flavor;

    AccessCritical<MyStructC> critical;
    AccessFlavor<MyStructC> flavor;
    MyStructC() : critical(*this), flavor(*this) {}
};
void processFlavor(Flavor *flavor)
{
    flavor->SetFlavor(flavor->GetFlavor() * 3);
}
void processCritical(Critical *critical)
{
    critical->SetA(critical->GetA() + critical->GetB());
}
int main() {
    MyStructA a;
    a.critical.SetA(2);
    a.critical.SetB(3);
    processCritical(& a.critical);

    MyStructB b;
    b.flavor.SetFlavor(4);
    processFlavor(& b.flavor);

    MyStructC c;
    c.critical.SetA(20);
    c.critical.SetB(30);
    c.flavor.SetFlavor(40);
    processFlavor(& c.flavor);
    processCritical(& c.critical);

    cerr << a.critical.GetA() << ' ' << a.critical.GetB() << endl;
    cerr << b.flavor.GetFlavor() << endl;
    cerr << c.critical.GetA() << ' ' << c.critical.GetB() << endl;
    cerr << c.flavor.GetFlavor() << endl;

    return 0;
}
类关键
{
公众:
虚拟int GetA()=0;
虚拟int GetB()=0;
虚空集a(int a)=0;
虚拟空位收缩(int b)=0;
};
风味
{
公众:
虚拟int GetFlavor()=0;
虚虚空SetFlavor(int a)=0;
};
模板
类访问关键:公共关键
{
公众:
AccessCritical(T&ref):数据(ref){}
int GetA(){return(data.m_a);}
int GetB(){return(data.m_b);}
void SetA(int a){data.m_a=a;}
void SetB(int b){data.m_b=b;}
私人:
T&data;
};
模板
类AccessFlavor:公共风味
{
公众:
AccessFlavor(T&ref):数据(ref){}
int GetFlavor(){return(data.m_flavor);}
void SetFlavor(int flavor){data.m_flavor=flavor;}
私人:
T&data;
};
结构MyStructA{
国际货币基金组织;
访问关键;
MyStructA():临界(*this){}
};
结构MyStructB{
int m_风味;
风味;
MyStructB():flavor(*this){}
};
结构MyStructC{
国际货币基金组织;
int m_风味;
访问关键;
风味;
MyStructC():critical(*this),flavor(*this){}
};
void processFlavor(Flavor*Flavor)
{
风味->设置风味(风味->获取风味()*3);
}
无效处理关键(关键*关键)
{
临界->SetA(临界->GetA()+临界->GetB());
}
int main(){
MyStructA a;
a、 关键毛(2);
a、 严重的挫折(3);
过程关键(a.critical);
MyStructB;
b、 香精(4);
工艺香精(b.flavor&b.flavor);
MyStructC;
c、 临界毛(20);
c、 严重。挫折(30);
c、 香精(40);
过程风味(c.flavor&c.flavor);
过程关键型(&c.critical);

cerr在我看来,这个层次结构的类只不过是数据桶,它们实际上除了充当某个底层数据模型的访问器之外,什么都不做。也许只是将您的设计限制为一个具有关键访问器的类,以及另一个更通用的命名属性方法(即std::string GetStringProperty)(std::string key){}?

我的建议:找一位最有耐心、熟悉此代码的同事,并向他们提出以下问题。我假设由于IP问题,您没有发布更完整的示例。这使得很难提供好的建议

基于您的第一个代码示例,我会说只使用带有公共数据的结构,而不使用访问器。但是如果我看到了真正的代码,我可能会改变我的想法

对于您的第二个代码示例:一个好处是您可以让另一个类依赖于
CriticalFlavor
,而不知道任何关于
Critical
(例如,可以用于实现类似桥接模式的东西).但是,如果这种潜在的好处在您的情况下不是实际的好处,那么它只会使您的代码变得不必要的复杂和雅格尼(可能)


审阅者的评论:

基类应该是抽象的

我会说,“基类通常应该至少有一个虚方法,而不是析构函数”。如果没有,那么它只是在其他类之间共享公共代码或数据的一种手段;试着使用组合

大多数情况下,这些虚拟方法中至少有一个是纯虚拟的,因此基类是抽象的。但有时每个虚拟方法都有一个很好的默认实现,子类会选择要重写的方法。在这种情况下,请保护基类构造函数,以防基类构造函数实例化党卫军

基类中不建议使用受保护的成员

…而且它们在非基类中完全没有意义,所以这个建议基本上是说永远不要使用它们

什么时候建议使用受保护的成员变量?很少使用。您的代码示例不够现实,无法确定您要做什么或如何最好地编写。成员受到保护,但有公共getter/setter,因此它们基本上是公共的

按接口设计

不要被这件事冲昏头脑,否则你可能会为一个简单得惊人的任务而得到一个极其复杂的设计。在界面有意义的地方使用。如果没有看到一些“调用代码”,很难判断它们是否有意义使用
Critical
及其子类的。谁调用
GetFlavor
GetTwist

调用代码是否仅通过
Critical
接口与
Critical
子类交互,或者调用代码是否知道特定子类和调用特定子类方法?您是否向
Critical
添加了接口方法以提供对数据/函数的访问