Назовите членов базового класса из производного класса - PullRequest
7 голосов
/ 27 июня 2011
class A {
    public:
        void fa() {
        }
    };

class B : public A{
public:
    void fb() {
    }
};

class C : public A, public B {
public:
    void fc() {
        //call A::fa(), not B::A::fa();
    }
};

Как вызвать A::fa() из функции C::fc().

GCC предупреждает с помощью direct base A inaccessible in C due to ambiguity, означает ли это, что нет прямого способа ссылаться на членов базового класса?

Ответы [ 5 ]

8 голосов
/ 27 июня 2011

Один из вариантов - создать класс-заглушку, который можно использовать для приведения к подобъекту правого базового класса:

struct A {
    void fa() { }
};

struct B : A {
    void fb() { }
};

// Use a stub class that we can cast through:
struct A_ : A { };

struct C : A_, B {
    void fc() {
        implicit_cast<A_&>(*this).fa();
    }
};

Где implicit_cast определяется как:

template <typename T> struct identity { typedef T type; }

template <typename T>
T implicit_cast(typename identity<T>::type& x) { return x; }
5 голосов
/ 27 июня 2011

Я только что нашел следующую информацию из стандарта ISO C ++ 2003 (10.1.3)

A class shall not be specified as a direct base class of a derived class more than once. [Note: a class can be
an indirect base class more than once and can be a direct and an indirect base class. There are limited
things that can be done with such a class. The non-static data members and member functions of the direct
base class cannot be referred to in the scope of the derived class. However, the static members, enumerations
and types can be unambiguously referred to.

Это означает, что прямого пути нет: (

1 голос
/ 27 июня 2011

Я только что скомпилировал ваш код на codepad.org , достаточно указать A::fa() для вызова fa () из вашей функции C::fc().

 void fc() {
       A::fa();
    }

Ниже приведенссылка на кодовую панель с вашим кодом.

http://codepad.org/NMFTFRnt

0 голосов
/ 27 июня 2011

Не думаю, что вы можете делать то, что хотите. Здесь есть неоднозначность: когда вы говорите A::fa(), он все равно не сообщает компилятору, какой A объект использовать. Нет доступа к классу A. Вот что говорит вам предупреждение.

Это похоже на ужасно странную конструкцию. Публичное наследование должно использоваться для отношений is-a. Вы говорите, что C - это A дважды? Это не имеет смысла. И это говорит о том, что это либо искусственный пример, который никогда не появится на практике, либо вам следует пересмотреть этот замысел.

0 голосов
/ 27 июня 2011

Вы можете использовать virtual наследование, чтобы преодолеть такую ​​проблему:

class B : virtual public A {

Теперь вы можете использовать A::fa() просто у ребенка class C.

void fc()
{
  fa();
}

ОднакоОбычно я не вижу никакой практической необходимости наследовать class A снова в class C, когда B уже public союзник, наследующий A.Итак, в вашем случае вы можете сделать это просто:

class C : public B {

Редактировать :

Если вы хотите 2 экземпляра для A.тогда прямой экземпляр, который вы намереваетесь сделать, можно сделать объектом C:

class C : public B {
  A obj;

, поскольку наличие наследуемого A напрямую не может быть использовано в любом случае.Вы не можете объявить какой-либо указатель или ссылку на него в области действия C.

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