Множественное наследование указывает желаемую виртуальную функцию, не перерисовывая ее - PullRequest
1 голос
/ 28 февраля 2012

Я хочу знать, есть ли способ указать, что при множественном наследовании одна из виртуальных функций базовых классов становится единым виртуальным определением. Единственный способ, которым я вижу это, - написать явное определение этой функции в производном классе и явно вызвать один из базовых классов. Это громоздко, и я надеялся, что using может помочь, но это не так.

Например, в приведенном ниже коде я должен определить C::value, хотя я просто хочу переслать версию класса B. Есть ли более простой способ?

#include <iostream>

using namespace std;

struct A
{
    virtual char const * value() const
    { return "A"; }
};

struct B
{
    virtual char const * value() const
    { return "B"; }
};

class C : public A, public B
{
public:
    //using B::value;
    virtual char const * value() const
    { return B::value(); }
};

int main()
{
    C obj;
    cout << obj.value() << endl;

    A * ptr = &obj;
    cout << ptr->value() << endl;
}

Некоторые заметки:

  • в данном конкретном случае виртуальное наследование класса A не является вариантом для класса B - мне нужна правильная цепочка построения вплоть до базовой
  • Теоретически структура B также может использоваться независимо от A, но здесь дело обстоит не так (в случае, если она предоставляет другие варианты)
  • value может быть помечен как чисто виртуальный, если это как-то помогает, но я не верю, что это так.
  • есть другие классы, которые происходят от A, но не от B
  • , чтобы быть понятным, однако "func" вызывается на C через любой указатель типа, должен привести к "B"

Я подозреваю, что ответ может быть "Нет", но какое-то подтверждение было бы хорошо. Такое ощущение, что язык должен поддерживать этот шаблон.

Ответы [ 4 ]

2 голосов
/ 28 февраля 2012

Единственный способ сделать это - написать явное определение эта функция в производном классе ..., и я надеялся, используя мощь помощь

Ключевое слово

using в вашем контексте используется только для приведения имен в текущую область (используется против скрытия имени). Предположим, что запрашиваемая вами функция уже есть. Теперь посмотрите следующие модифицированные коды:

struct A
{
  virtual char const * value() const
  { return "A"; }

  void value (double);  // new function
};

class C : public A, public B
{
public:
  using B::value;
  void value(int);  // new function
};

Предположим, у нас есть функции с тем же именем, что и value(int) в C и value(double) в A. Эти 2 функции не имеют ничего общего с virtual value() и используются с объектом C.

Как вы будете использовать A::value(double) с C объектом? Естественно, вы должны сделать using A::value; в теле C. Теперь из-за этого в качестве побочного эффекта у нас есть 2 virtual соответствия функции: A::value() const и B::value() const!
Что выбрать при вызове с A* или B*?

Это только один пример, но могут быть и другие проблемы. Все, что вы упомянули в своем вопросе, - лучший способ добиться правильного результата. В нем прямо сказано, что C::value() const является оберткой вокруг B::value() const.

0 голосов
/ 28 февраля 2012

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

Вывод:

B

A

#include <iostream> 

using namespace std; 

struct A 
{ 
    char const* value() const
    {
        return valueImpl();
    }
protected:
    virtual char const * valueImpl() const 
    { return "A"; } 
}; 

struct B 
{ 
    char const* value() const
    {
        return valueImpl();
    }
protected:
    virtual char const * valueImpl() const 
    { return "B"; } 
}; 

class C : public A, public B 
{ 
public:
   using B::value;

}; 

int main() 
{ 
    C obj; 
    cout << obj.value() << endl; 

    A * ptr = &obj; 
    cout << ptr->value() << endl; 
}
0 голосов
/ 28 февраля 2012

Нет. Нет другого способа сделать это, кроме явного вызова функции с использованием разрешения двоичной области видимости operator::.

0 голосов
/ 28 февраля 2012

Множественное наследование настолько редко, а стоимость написания такой функции настолько тривиальна, что она не стоит языковой функции, и я, конечно, не знаю ни одной, которая обеспечивала бы такую ​​функциональность.

Единственная вещь using аффекты - это видимость, которая здесь не является проблемой, поэтому она, безусловно, не может помочь.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...