禁止切片以保持多个父类属性同步

时间:2016-03-23 13:42:34

标签: c++

我从两个父类派生一个对象。这两个父母各有不同类型的属性,但我希望孩子保持彼此同步。但是,我想禁止该库的用户通过切片意外地将Child视为ParentAParentB。例如:

#include <iostream>

class ParentA
{
public:
    void modify()
    {
        std::cout << "modifyA" << std::endl;
    }

    void readA()
    {
        std::cout << "readA" << std::endl;
    }
};

class ParentB
{
public:
    void modify()
    {
        std::cout << "modifyB" << std::endl;
    }
    void readB()
    {
        std::cout << "readB" << std::endl;
    }
};

class Child : public ParentA, public ParentB
{
public:
    void modify()
    {
        // Do some bounds checking to make sure ParentA and ParentB stay in sync, then:
        ParentA::modify();
        ParentB::modify();
        std::cout << "modifyChild" << std::endl;
    }
};

void Change(ParentA object)
{
    object.modify();
}

int main()
{
    std::cout << "This is standard:" << std::endl;
    ParentA parentA;
    parentA.modify();

    ParentB parentB;
    parentB.modify();

    Child child;
    child.readA();
    child.readB();
    child.modify();

    std::cout << "Want to avoid this:" << std::endl;
    Change(child);

    return 0;
}

Change(child);来电调用ParentA的{​​{1}}功能,其中modify()属性可能与ParentA属性不同步, ParentB处于不良状态。

Childread*()中有许多功能(此处为ParentA个,我不想从ParentB手动转发,所以我可以私下派生。

有没有办法让这个Child调用产生编译错误(不改变Change(child)的签名)?

2 个答案:

答案 0 :(得分:2)

实际上有一种方法可以做到这一点(尽管你说它不喜欢它):privateprotected继承是实现你想要的C ++机制。

请记住,既然你的孩子班级试图在A和B之间保持某种不变性,如果你继承public,有人会找到一种方法来使用A或B的界面来违反不变量所以你需要防止那些直接在孩子身上使用的东西,这是受限制的继承完美的。

如果父母中有一些不影响两类不变量的方法,你可以using那些方法进入Child的公共部分。

答案 1 :(得分:1)

正如评论所说,最简洁的方法可能是从ParentAParentB继承private并转发所需的功能。

我有另一个想法:您可以将ParentAParentB的功能提取到2个抽象类(AbstractParentAAbstractParentB)中,并将这些类用作基类。

这会给你想要的行为:

#include <iostream>

class AbstractParentA
{
    virtual void no_instance() = 0;

public:
    void modify()
    {
        std::cout << "modifyA" << std::endl;
    }

    void readA()
    {
        std::cout << "readA" << std::endl;
    }
};

class AbstractParentB
{
    virtual void no_instance() = 0;

public:
    void modify()
    {
        std::cout << "modifyB" << std::endl;
    }
    void readB()
    {
        std::cout << "readB" << std::endl;
    }
};


class ParentA : public AbstractParentA
{
    virtual void no_instance() override {}
};


class ParentB : public AbstractParentB
{
    virtual void no_instance() override {}
};

class Child : public AbstractParentA, public AbstractParentB
{
    virtual void no_instance() override {}

public:
    void modify()
    {
        // Do some bounds checking to make sure ParentA and ParentB stay in sync, then:
        AbstractParentA::modify();
        AbstractParentB::modify();
        std::cout << "modifyChild" << std::endl;
    }
};

void Change(ParentA object)
{
    object.modify();
}

int main()
{
    std::cout << "This is standard:" << std::endl;
    ParentA parentA;
    parentA.modify();

    ParentB parentB;
    parentB.modify();

    Child child;
    child.readA();
    child.readB();
    child.modify();

    std::cout << "Want to avoid this:" << std::endl;
    Change(child);

    return 0;
}
  

错误C2664:'void Change(ParentA)':无法从'Child'转换参数1

     

注意:没有可用于执行此转换的用户定义转换运算符,或者无法调用运算符