Здравствуйте! Объясните, плз, почему функции базового класса не привязываются к виртуальным функциям интерфейса?
class I
{
public:
virtual void f1(void) = 0;
};
class A
{
public:
void f1(void) { /*...*/ }
};
class B : public A, public I
{
//...
};
main()
{
B b;
}
В итоге будет выдана ошибка о том что класс "B" абстрактный т.к. f1 не определена. Но почему? Чисто технически, если бы f1 была определена в "B" а не в "A", то ее код ничем бы не отличался. Так что мешает компилятору ее использовать?
Здравствуйте, Аноним, Вы писали: А>Здравствуйте! Объясните, плз, почему функции базового класса не привязываются к виртуальным функциям интерфейса?
Скрытый текст
А>
class I
А>{
А>public:
А> virtual void f1(void) = 0;
А>};
А>class A
А>{
А>public:
А> void f1(void) { /*...*/ }
А>};
А>class B : public A, public I
А>{
А> //...
А>};
А>main()
А>{
А> B b;
А>}
А>В итоге будет выдана ошибка о том что класс "B" абстрактный т.к. f1 не определена. Но почему? Чисто технически, если бы f1 была определена в "B" а не в "A", то ее код ничем бы не отличался. Так что мешает компилятору ее использовать?
B * b = new B();
A * a = new A();
A * ab = &b;
a->f1(); // f1 не делает virtual call
ab->f1();// f1 не делает virtual call
Здравствуйте, Аноним, Вы писали:
А>Здравствуйте! Объясните, плз, почему функции базового класса не привязываются к виртуальным функциям интерфейса?
А>
class I
А>{
А>public:
А> virtual void f1(void) = 0;
А>};
А>class A
А>{
А>public:
А> void f1(void) { /*...*/ }
А>};
А>class B : public A, public I
А>{
А> //...
А>};
А>main()
А>{
А> B b;
А>}
А>В итоге будет выдана ошибка о том что класс "B" абстрактный т.к. f1 не определена. Но почему? Чисто технически, если бы f1 была определена в "B" а не в "A", то ее код ничем бы не отличался. Так что мешает компилятору ее использовать?
Это совершенно другая функция. A::f1 определена, все хорошо. Но I::f1 осталась не определенной.
class A не наследуется от class I, поэтому
его void f1(void) никак не относится к
функции
virtual void f1(void)
из класса I.
(и кстати A::f1 даже не является виртуальной).
> Чисто технически, если бы f1 была определена в "B" а не в "A", то ее код > ничем бы не отличался.
Чисто технически если бы она была в B, то зрительно код бы не отличался
(потому что и кода-то там нет сейчас), но также чисто технически
это было бы переопределение I::f1, а поскольку f1 в A, то это просто
разные функции, по случайности имеющие одно и то же имя 'f1'.
Добавлю к предыдущим ораторам, что если хочется использовать именно так, то и наследование должно быть дважды и виртуальным.
class I
{
public:
virtual void f1(void) = 0;
};
class A : public virtual I
{
public:
void f1(void) { /*...*/ }
};
class B : public A, publicvirtualI
{
//...
};
main()
{
B b;
}
Здравствуйте, Аноним, Вы писали: А>Здравствуйте! Объясните, плз, почему функции базового класса не привязываются к виртуальным функциям интерфейса?
Скрытый текст
А>
class I
А>{
А>public:
А> virtual void f1(void) = 0;
А>};
А>class A
А>{
А>public:
А> void f1(void) { /*...*/ }
А>};
А>class B : public A, public I
А>{
А> //...
А>};
А>main()
А>{
А> B b;
А>}
А>В итоге будет выдана ошибка о том что класс "B" абстрактный т.к. f1 не определена. Но почему? Чисто технически, если бы f1 была определена в "B" а не в "A", то ее код ничем бы не отличался. Так что мешает компилятору ее использовать?
Да, C++ после C# — это как реальность после сна. С пробуждением!
--
Справедливость выше закона. А человечность выше справедливости.
C>B * b = new B();
C>A * a = new A();
C>A * ab = &b;
a->>f1(); // f1 не делает virtual call
ab->>f1();// f1 не делает virtual call
C>
И? Во-первых компилятор это не скушает все по той же причине.
Во-вторых я не понял что вы хотели сказать. "f1 не делает virtual call" — да, разумеется, и "a" и "ab" это указатели на "A", и там нет virtual call. Но к чему вы это?
В-третьих я могу переписать пример и уже в базовом классе сделать f1 виртуальной, но это ничего не изменит. Хотя вызов уже пойдет через таблицу.
Здравствуйте, MasterZiv, Вы писали:
MZ>Чисто технически если бы она была в B, то зрительно код бы не отличался MZ>(потому что и кода-то там нет сейчас), но также чисто технически MZ>это было бы переопределение I::f1, а поскольку f1 в A, то это просто MZ>разные функции, по случайности имеющие одно и то же имя 'f1'.
Чисто технически, раз уж "В" унаследовала "А", то "А" является неотъемлемой частью "В", со всеми вытекающими.
И вообще мне всегда казалось что тело обычной ф-ии ничем не отличается от тела виртуальной. Различается только способ вызова.
Здравствуйте, johny5, Вы писали: J>Здравствуйте, Аноним, Вы писали: J>Добавлю к предыдущим ораторам, что если хочется использовать именно так, то и наследование должно быть дважды и виртуальным.
Скрытый текст
J>
J>class I
J>{
J>public:
J> virtual void f1(void) = 0;
J>};
J>class A : public virtual I
J>{
J>public:
J> void f1(void) { /*...*/ }
J>};
J>class B : public A, publicvirtualI
J>{
J> //...
J>};
J>main()
J>{
J> B b;
J>}
J>
Ну наконец реальный собеседник, а не очередной капитан очевидность.
Увы, изначально именно подобная схема и не сработала.
class I1
{
public:
virtual void f1(void) = 0;
};
class I2 : public I1
{
public:
virtual void f2(void) = 0;
};
class A : public I1
{
public:
void f1(void) { /*...*/ }
};
class B : public A, public I2
{
public:
void f2(void) { /*...*/ }
};
main()
{
B b;
}
Не работает. Правда вы еще и наследование делаете виртуальным... Но зачем оно здесь?
Здравствуйте, rg45, Вы писали:
R>Да, C++ после C# — это как реальность после сна. С пробуждением!
Спасибо!
Только маленькая поправочка. C++ после ASM и С — это как сон идиота пускающего слюни и неспособного выйти за рамки заплесневелой концепции придуманной еще при царе горохе.
ЗЫ
Звиняюсь что запостил вам два ответа предназначенных другим участникам. Не привычен мне этот древовидный форум.
jrk>I::f1 не более чем указатель в таблице вирт. ф-ий. Что мешает ему указывать на A::f1?
С чего бы вдруг? Почему не на foo в классе baz? Между A::f1 и I::f1 нет ничего общего. Совсем.
jrk>Только маленькая поправочка. C++ после ASM и С — это как сон идиота пускающего слюни и неспособного выйти за рамки заплесневелой концепции придуманной еще при царе горохе.
Не понимаю упрека Не нравится С++ — пиши на С. Можешь даже компилировать свой сишный код C++ компилятором в 90% случаев. И асмовские вставки делать. Какие проблемы?
> Чисто технически, раз уж "В" унаследовала "А", то "А" является неотъемлемой > частью "В", со всеми вытекающими. > > И вообще мне всегда казалось что тело обычной ф-ии ничем не отличается от тела > виртуальной. Различается только способ вызова.
> Не работает. Правда вы еще и наследование делаете виртуальным... Но зачем оно здесь?
Затем, чтобы работало. Ты бы пошёл что ли книжку какую почитал...
Объяснять проблемы множественного наследования в С++ в форуме при наличии
тонн литературы по С++ -- занятие неблагодарное.
Я к тому, что это не конкретная проблема, которую ты не можешь решить или не
понимаешь, это -- базовые универсальные знания, которые обсуждать на форуме
бессмысленно.