Алмазное наследование с шаблонным базовым классом: Base <Derived> - PullRequest
1 голос
/ 14 октября 2019

У меня проблема с алмазом при наследовании от шаблонного базового класса, который принимает класс-источник в качестве аргумента шаблона.

Обычно эта проблема решается с помощью виртуального наследования следующим образом:

class Base0
{
protected:
    int var = 0;
};

class Base1 : public virtual Base0
{
};

class Base2 : public virtual Base0
{

};

class Derived :
    public Base1,
    public Base2
{
public:
    void f()
    {
        var = 1; // OK single var
    }
};

Однако у меня естьэтот сценарий:

template<typename DERIVED_CLASS>
class TemplatedBase0
{
protected:
    int var = 0;
};

class Base1 : public virtual TemplatedBase0<Base1>
{
};

class Base2 : public virtual TemplatedBase0<Base2>
{

};

class Derived :
    public Base1,
    public Base2
{
public:
    void f()
    {
        var = 1; // ERROR: var is ambigous
    }
};

Я понимаю, что в вышеупомянутом случае шаблонный базовый класс не то же самое, т.е. задействованы 2 совершенно нереализованных базовых класса, и похоже, что виртуальное наследование не работает.

Итак, мой вопрос, есть ли способ заставить эту работу? какой дизайн / подход я должен использовать здесь?

Мне нужно иметь базовый класс в качестве шаблона, который принимает тип производного класса. но как сделать возможным наследование алмазов?

Ответы [ 2 ]

1 голос
/ 14 октября 2019

Если вы хотите иметь только один int var; в Derived, вам нужно переместить его в базовый класс без шаблона:

class GenericTemplatedBase0
{
  protected:
    int var = 0;
};

template<typename DERIVED_CLASS>
class TemplatedBase0 : virtual public GenericTemplatedBase0
{
    // ...
};

class Base1 : public TemplatedBase0<Base1>
{
};

class Base2 : public TemplatedBase0<Base2>
{
};

class Derived : public Base1, public Base2
{
  public:
    void f()
    {
        var = 1;
    }
};
1 голос
/ 14 октября 2019

В вашем коде нет бриллианта. Ваш Derived имеет два разных var с. В зависимости от того, что вы хотите написать:

Base1::var = 1;
Base2::var = 1;

но как сделать возможным наследование алмазов?

Не понятно, зачем вам алмаз. Если ваша цель состоит в том, чтобы иметь только один var в Derived, вам нужен другой дизайн.

...