C++ C++;来自具有相同名称成员的基类的多重继承

C++ C++;来自具有相同名称成员的基类的多重继承,c++,c++11,multiple-inheritance,C++,C++11,Multiple Inheritance,让我告诉你我的问题。我正在设计一组控制数字设备的类。该设备可在两种操作模式下工作。在第一种模式下,它可以执行一组特定的操作,而在第二种模式下,它可以执行另一组操作(两种模式之间可能有一些常见的操作)。我还可以在运行时更改设备的模式,以便在必要时在两种模式之间切换。与模式无关,设备使用相同的寄存器集 我想用每个模式一个基类来解决这个问题,所以当我需要第一组操作时,我可以有模式1的对象,当我需要第二组操作时,我可以有模式2的对象。然后我可以从这两个基类派生一个类,这样我就可以拥有执行所有操作的对象

让我告诉你我的问题。我正在设计一组控制数字设备的类。该设备可在两种操作模式下工作。在第一种模式下,它可以执行一组特定的操作,而在第二种模式下,它可以执行另一组操作(两种模式之间可能有一些常见的操作)。我还可以在运行时更改设备的模式,以便在必要时在两种模式之间切换。与模式无关,设备使用相同的寄存器集

我想用每个模式一个基类来解决这个问题,所以当我需要第一组操作时,我可以有模式1的对象,当我需要第二组操作时,我可以有模式2的对象。然后我可以从这两个基类派生一个类,这样我就可以拥有执行所有操作的对象

我的设计的问题是这两个基类有一些共同的函数和对相同寄存器的引用。因为我不能阻止成员的继承,所以在派生类中会有重复的成员。我知道我可以选择使用scope操作符访问哪个副本,但我仍然认为这是一个糟糕的设计

所以我的问题是:有没有一种惯用的方法来解决这个问题

如果没有正确或简单的方法来解决这个问题,我会考虑设计3个分层独立的类。我会有一些重复的代码,但这不是一个大问题,对吗

下面的代码(简化)用于说明:

class mode1
{
protected:
    volatile uint8_t& reg1;
    volatile uint8_t& reg2;
    uint8_t data; 
public:
    virtual void operation1() final { // do something }
    virtual void operation2() final { // do something }
    virtual void operation3() final { // do something } 
};


class mode2
{
protected:
    volatile uint8_t& reg1;
    volatile uint8_t& reg2;
    uint8_t data; 
public:
    virtual void operation4() final { // do something }
    virtual void operation2() final { // do something }
    virtual void operation5() final { // do something } 
};


class mode1and2 : public mode1, public mode2
{
public:
    void operation6() { // do something }
    void operation7() { // do something }
};

注意模式1和模式2具有操作2和所有数据成员的共同点。

状态设计模式看起来很适合您的情况。
作为一个最低限度的工作示例:

#include<memory>
#include<iostream>

struct Behavior {
    virtual void f() = 0;
    virtual void g() = 0;
};

struct NullBehavior: Behavior {
    void f() override {}
    void g() override {}
};

struct Mode1: Behavior {
    void f() override { std::cout << "mode 1 - f" << std::endl; }
    void g() override { std::cout << "mode 1 - g" << std::endl; }
};

struct Mode2: Behavior {
    void f() override { std::cout << "mode 2 - f" << std::endl; }
    void g() override { std::cout << "mode 2 - g" << std::endl; }
};

struct Device {
    template<typename B>
    void set() { behavior = std::unique_ptr<Behavior>{new B}; }

    void f() { behavior->f(); }
    void g() { behavior->g(); }

private:
    std::unique_ptr<Behavior> behavior{new NullBehavior};
};

int main() {
    Device device;
    device.f();
    device.g();

    device.set<Mode1>();
    device.f();
    device.g();

    device.set<Mode2>();
    device.f();
    device.g();
}
#包括
#包括
结构行为{
虚空f()=0;
虚空g()=0;
};
结构NullBehavior:行为{
void f()重写{}
void g()重写{}
};
结构模式1:行为{

void f()override{std::cout我将
mode1
mode2
的公共部分放在一个公共基类中,比如说
common
,由数据和成员函数
operation2
组成。然后,再加上虚拟继承,您可以在同一数据上有两个视图,甚至在需要时也可以同时查看

class common {
    friend class mode1;
    friend class mode2;
protected:
    volatile uint8_t& reg1;
    volatile uint8_t& reg2;
    uint8_t data;

public:
    virtual void operation2() final { // do something
    };

};

class mode1 : public virtual common
{
public:
    virtual void operation1() final { // do something
    };
    virtual void operation3() final { // do something }
    };
};

class mode2 : public virtual common
{
public:
    virtual void operation4() final { // do something
    }
    virtual void operation5() final { // do something
    }
};


class mode1and2 : public mode1, public mode2
{
public:
    void operation6() { // do something }
    };
    void operation7() { // do something }
    };
};

你为什么想要一个执行所有操作的对象?你尝试了什么?看看虚拟继承。@immibis,因为我可以动态更改设备的模式。所以它可能需要知道如何执行所有操作。@Stephannechner,数据成员的虚拟继承?什么?我现在正在阅读有关虚拟继承的内容。看起来像t他的正是我想要的谢谢Stephan。
class common {
    friend class mode1;
    friend class mode2;
protected:
    volatile uint8_t& reg1;
    volatile uint8_t& reg2;
    uint8_t data;

public:
    virtual void operation2() final { // do something
    };

};

class mode1 : public virtual common
{
public:
    virtual void operation1() final { // do something
    };
    virtual void operation3() final { // do something }
    };
};

class mode2 : public virtual common
{
public:
    virtual void operation4() final { // do something
    }
    virtual void operation5() final { // do something
    }
};


class mode1and2 : public mode1, public mode2
{
public:
    void operation6() { // do something }
    };
    void operation7() { // do something }
    };
};