Предположим, есть этот интерфейс:
class A{
public:
virtual foo()=0;
};
И класс B
который реализует этот интерфейс:
class B:public A{
public:
virtual foo(){} //Foo implemented by B
}
Наконец, класс C
который имеет классы A
а также B
в качестве базовых классов:
Class C : public A, public B {
};
Мой вопрос, есть способ сказать компилятору, что реализация для foo
тот из класса B
без явного вызова B::foo()
?
Как отметил @BenVoigt в комментариях, приведенный ниже ответ работает только из-за ошибки в g ++ (что означает, что он не гарантированно продолжит работать, и он определенно не переносим). Таким образом, хотя он может делать то, что вы хотите, если вы используете определенный (глючный) компилятор, это не вариант, который вы должны использовать.
Делать использование виртуальное наследство хоть.
Это не совсем тот сценарий, что код в вопросе подразумевается, но предложение
Мой вопрос, есть способ сказать компилятору, что
Реализация для Foo из класса B, не делая
явный вызов B :: foo ()?
кажется, что запрашивает синтаксис для различения нескольких базовых версий функции без использования ::
Классификатор.
Вы можете сделать это с using
директива:
#include <iostream>
class A {
public:
A(){}
virtual void foo(){std::cout<<"A func";}
};
class B: virtual public A {
public:
B(){}
virtual void foo(){std::cout<<"B func";}
};
class C:virtual public A, virtual public B {
public:
C(){}
using A::foo; // tells the compiler which version to use
// could also say using B::foo, though this is unnecessary
};
int main() {
C c;
c.foo(); // prints "A func"return 0;
}
Конечно, сам код в вопросе не требует этого вообще, как указывали другие ответы.
Просто используйте виртуальное наследование, чтобы A
подобъект предоставлен B
это тот же объект, используемый в C
,
Или пиши class C : public B
… это будет неявно использоваться как A
во всяком случае, через базовый класс B
,
До того, как вопрос был отредактирован:
B::foo
не совместим с A::foo
,
Требуемая подпись
ReturnType /* missing from question */ foo(A* const this /* this parameter is implicit */);
Но B::foo
имеет подпись
ReturnType foo(B* const this);
A*
, который будет передан в виртуальную функцию, не является B*
, чего требует реализация. Если B
унаследованный от A
то компилятор сгенерирует B::foo
принять A* const subobject
и найти B* const this
объект из этого указателя подобъекта. Но B::foo
не знает об отношениях в C
,
Поскольку в вашем примере есть два базовых класса (которые могут быть проблемой дизайна / запахом дизайна, я бы рассмотрел это), вам придется явно вызывать реализацию, к которой вы стремитесь, будь то A::foo()
или же B:foo()
,
Если все, что B делает, это обеспечивает реализацию foo()
Я бы посоветовал переместить реализацию в A (вы можете предоставить реализацию для чисто виртуальной функции), но даже в этом случае вам придется вызывать ее через ее полное имя.