Здравствуйте, machine1, Вы писали:
M>Привет,
M>незнаю как сделать, хотелось что-то типа этого:
M>
M>class A
M>{
M>public:
M> virtual void f() = 0;
M>};
M>class B
M>{
M>public:
M> virtual void f() = 0;
M>};
M>class AB : public A, public B
M>{
M>public:
M> void A::f() {/*тут реализация*/}
M> void B::f() {/*тут реализация*/}
M>}
M>
Смысл виртуального множественного наследования в том, чтобы вызвать нужную функцию в зависимости от типа:
class A
{
public:
void f(){ cout << "A::f()" << endl;}
};
class B
{
public:
void f(){ cout << "B::f()" << endl;}
};
class AB : virtual public A, virtual public B
{
};
int main(int argc, char* argv[])
{
A *a = new AB;
B *b = new AB;
a->f();
b->f();
return 0;
}
А смысл чисто виртуальной функции в том, чтобы возложить реализацию на производный класс:
class A
{
public:
virtual void f() = 0;
};
class B
{
public:
virtual void f() = 0;
};
class AB : virtual public A, virtual public B
{
public:
void f() {
cout << "f()" << endl;
}
};
int main(int argc, char* argv[])
{
AB *ab = new AB;
ab->f();
return 0;
}
Код в вопросе можно поправить так:
class A
{
public:
virtual void fA() = 0;
};
class B
{
public:
virtual void fB() = 0;
};
class AB : public A, public B
{
public:
void fA() {
cout << "A::fA()";
}
void fB() {
cout << "B::fB()";
}
};
Или так:
class A
{
public:
void f(){ cout << "A::f()" << endl;}
};
class B
{
public:
void f(){ cout << "B::f()" << endl;}
};
class AB : virtual public A, virtual public B
{
public:
void f() {
cout << "AB::f()" << endl;
}
};
int main(){
AB *ab = new AB;
ab->f();
ab->A::f();
ab->B::f();
}
Кстати gnu-шный компиллятор ругается на этот код по-другому:
error: cannot declare member function `A::f' within `AB'
error: cannot declare member function `B::f' within `AB'
Да простит меня Аноним, но я опять буду ссылаться на Саттера.
P>Смысл виртуального множественного наследования в том, чтобы вызвать нужную функцию в зависимости от типа:
Нет, не так.
Виртуальное наследование предотвращает создание двух экземпларов базового класса.
class Base {};
class DerA : public Base {};
class DerB : public Base {};
class DerDer1 : public DerA, public DerB {}; // Данные класса Base бублируюутся.
class DerDer2 : virtual public DerA, virtual public DerB {}; // А тут вроде нет.
А все варианты, представленные ниже по моему не соответствуют начальной задумке
P>
P>class A
P>{
P>public:
P> void f(){ cout << "A::f()" << endl;}
P>};
P>class B
P>{
P>public:
P> void f(){ cout << "B::f()" << endl;}
P>};
P>class AB : virtual public A, virtual public B
P>{
P>};
P>int main(int argc, char* argv[])
P>{
P> A *a = new AB;
P> B *b = new AB;
a->>f();
b->>f();
P> return 0;
P>}
P>
P>А смысл чисто виртуальной функции в том, чтобы возложить реализацию на производный класс: P>
P>class A
P>{
P>public:
P> virtual void f() = 0;
P>};
P>class B
P>{
P>public:
P> virtual void f() = 0;
P>};
P>class AB : virtual public A, virtual public B
P>{
P>public:
P> void f() {
P> cout << "f()" << endl;
P> }
P>};
P>int main(int argc, char* argv[])
P>{
P> AB *ab = new AB;
ab->>f();
P> return 0;
P>}
P>
P>Код в вопросе можно поправить так: P>
P>class A
P>{
P>public:
P> virtual void fA() = 0;
P>};
P>class B
P>{
P>public:
P> virtual void fB() = 0;
P>};
P>class AB : public A, public B
P>{
P>public:
P> void fA() {
P> cout << "A::fA()";
P> }
P> void fB() {
P> cout << "B::fB()";
P> }
P>};
P>
P>Или так: P>
P>class A
P>{
P>public:
P> void f(){ cout << "A::f()" << endl;}
P>};
P>class B
P>{
P>public:
P> void f(){ cout << "B::f()" << endl;}
P>};
P>class AB : virtual public A, virtual public B
P>{
P>public:
P> void f() {
P> cout << "AB::f()" << endl;
P> }
P>};
P>int main(){
P> AB *ab = new AB;
ab->>f();
ab->>A::f();
ab->>B::f();
P>}
P>
P>Кстати gnu-шный компиллятор ругается на этот код по-другому: P>
P>error: cannot declare member function `A::f' within `AB'
P>error: cannot declare member function `B::f' within `AB'
class A
{
public:
virtual void f() = 0;
};
class B
{
public:
virtual void f() = 0;
};
class AB : public A, public B
{
public:
void A::f() {/*тут реализация*/}
void B::f() {/*тут реализация*/}
}
22.09.04 22:00: Оставлено модератором в 'C/C++' — Павел Кузнецов
Здравствуйте, _nn_, Вы писали:
__>Код правильный, что вас смущает ?
Не компилируется (vc6):
E:\source\test\test.cpp(22) : error C2838: illegal qualified name in member declaration
E:\source\test\test.cpp(23) : error C2628: 'AB' followed by 'void' is illegal (did you forget a ';'?)
E:\source\test\test.cpp(23) : error C2259: 'AB' : cannot instantiate abstract class due to following members:
E:\source\test\test.cpp(19) : see declaration of 'AB'
E:\source\test\test.cpp(23) : warning C4259: 'void __thiscall A::f(void)' : pure virtual function was not defined
E:\source\test\test.cpp(10) : see declaration of 'f'
E:\source\test\test.cpp(23) : warning C4259: 'void __thiscall B::f(void)' : pure virtual function was not defined
E:\source\test\test.cpp(16) : see declaration of 'f'
E:\source\test\test.cpp(23) : error C2556: 'class AB __thiscall B::f(void)' : overloaded function differs only by return type from 'void __thiscall B::f(void)'
E:\source\test\test.cpp(16) : see declaration of 'f'
E:\source\test\test.cpp(24) : error C2143: syntax error : missing ';' before '}'
E:\source\test\test.cpp(24) : error C2143: syntax error : missing ';' before '}'
E:\source\test\test.cpp(24) : error C2143: syntax error : missing ';' before '}'
M>E:\source\test\test.cpp(23) : error C2628: 'AB' followed by 'void' is illegal (did you forget a ';'?)
M>E:\source\test\test.cpp(24) : error C2143: syntax error : missing ';' before '}'
M>E:\source\test\test.cpp(24) : error C2143: syntax error : missing ';' before '}'
M>E:\source\test\test.cpp(24) : error C2143: syntax error : missing ';' before '}'
M>
уважаемый, а вы с английским в ладах? компилятор 3 раза тыкнул носом в ошибку и 1 раз подсказал. я бы посоветовал, перед тем как лезть на рсдн посидеть подумать хоть минуту над ошибкой и прочесть лок компилятора, всё же вроде понятно у него написано, даже строчки где ошибка произошла указаны. обычно такой разжованости от него редко ждешь, а тут...
"Man feed machine
Machine feed man"
Peter Gabriel — OVO — The Tower That Ate People
Re[4]: множественное наследование и полиморфизм
От:
Аноним
Дата:
22.09.04 09:49
Оценка:
class A
{
public:
virtual void f() = 0;
};
class Prokladka: public A
{
public:
virtual void f_() = 0;
virtual void f()
{
f_();
}
};
class B
{
public:
virtual void f() = 0;
};
class AB : public Prokladka, public B
{
public:
void f_() {/*тут реализация*/}
void f() {/*тут реализация*/}
}
Не помню точно как у Саттера, но точно не так.
Одно верно: нужен промежуточный класс.
class A
{
public:
virtual void f() = 0;
};
class Proxy_A: public A
{
protected:
virtual void f_A() = 0;
virtual void f()
{
f_A();
}
};
class Proxy_B: public B
{
protected:
virtual void f_B() = 0;
virtual void f()
{
f_B();
}
};
class AB : public Proxy_A, public Proxy_B
{
public:
void f_A() {/*тут реализация*/}
void f_B() {/*тут реализация*/}
}
В таком случае из класса Proxy_X ф-ии вызываться не будут.
А так будет вызываться нужная ф-ия.
AB* pAB = new AB;
A* pA = pAB;
B* pB = pAB;
pA->f(); pB->f();
Здравствуйте, Shhady, Вы писали:
S>уважаемый, а вы с английским в ладах? компилятор 3 раза тыкнул носом в ошибку и 1 раз подсказал. я бы посоветовал, перед тем как лезть на рсдн посидеть подумать хоть минуту над ошибкой и прочесть лок компилятора, всё же вроде понятно у него написано, даже строчки где ошибка произошла указаны. обычно такой разжованости от него редко ждешь, а тут...
Полный текст, тыкнете мне где не хвататет точки с запятой:
// test.cpp : Defines the entry point for the console application.
//#include"stdafx.h"class A
{
public:
virtual void f() = 0;
};
class B
{
public:
virtual void f() = 0;
};
class AB : public A, public B
{
public:
void A::f() {}
void B::f() {}
};
int main(int argc, char* argv[])
{
return 0;
}
:: machine1
Re[4]: множественное наследование и полиморфизм
От:
Аноним
Дата:
22.09.04 09:57
Оценка:
Т.е., по-твоему, легальной является конструкция вида
class A
{
public:
virtual void fun() = 0;
};
class D : public A
{
public:
void A::fun(){}
}
Здравствуйте, machine1, Вы писали:
M>Полный текст, тыкнете мне где не хвататет точки с запятой:
Под рукой vc6 нет, есть vc7. Всё компилит. Просто так как опять таки нету под рукой vc6 и видя лог компилятора, и видя ошибочный листинг из первого поста, у меня сложилось именно такое впечатление, что вы даже не читаете, на что он ругается. Ну хорошо, приведите мне новый лог последнего поста.
"Man feed machine
Machine feed man"
Peter Gabriel — OVO — The Tower That Ate People
Здравствуйте, Shhady, Вы писали:
S>Под рукой vc6 нет, есть vc7. Всё компилит. Просто так как опять таки нету под рукой vc6 и видя лог компилятора, и видя ошибочный листинг из первого поста, у меня сложилось именно такое впечатление, что вы даже не читаете, на что он ругается. Ну хорошо, приведите мне новый лог последнего поста.
Deleting intermediate files and output files for project 'test - Win32 Debug'.
--------------------Configuration: test - Win32 Debug--------------------
Compiling...
StdAfx.cpp
Compiling...
test.cpp
E:\source\test\test.cpp(22) : error C2838: illegal qualified name in member declaration
E:\source\test\test.cpp(23) : error C2628: 'AB' followed by 'void' is illegal (did you forget a ';'?)
E:\source\test\test.cpp(23) : error C2259: 'AB' : cannot instantiate abstract class due to following members:
E:\source\test\test.cpp(19) : see declaration of 'AB'
E:\source\test\test.cpp(23) : warning C4259: 'void __thiscall A::f(void)' : pure virtual function was not defined
E:\source\test\test.cpp(10) : see declaration of 'f'
E:\source\test\test.cpp(23) : warning C4259: 'void __thiscall B::f(void)' : pure virtual function was not defined
E:\source\test\test.cpp(16) : see declaration of 'f'
E:\source\test\test.cpp(23) : error C2556: 'class AB __thiscall B::f(void)' : overloaded function differs only by return type from 'void __thiscall B::f(void)'
E:\source\test\test.cpp(16) : see declaration of 'f'
E:\source\test\test.cpp(24) : error C2143: syntax error : missing ';' before '}'
E:\source\test\test.cpp(24) : error C2143: syntax error : missing ';' before '}'
E:\source\test\test.cpp(24) : error C2143: syntax error : missing ';' before '}'
Error executing cl.exe.
test.exe - 7 error(s), 2 warning(s)
M>Deleting intermediate files and output files for project 'test - Win32 Debug'.
M>--------------------Configuration: test - Win32 Debug--------------------
M>Compiling...
M>StdAfx.cpp
M>Compiling...
M>test.cpp
M>E:\source\test\test.cpp(22) : error C2838: illegal qualified name in member declaration
M>E:\source\test\test.cpp(23) : error C2628: 'AB' followed by 'void' is illegal (did you forget a ';'?)
M>E:\source\test\test.cpp(23) : error C2259: 'AB' : cannot instantiate abstract class due to following members:
M> E:\source\test\test.cpp(19) : see declaration of 'AB'
M>E:\source\test\test.cpp(23) : warning C4259: 'void __thiscall A::f(void)' : pure virtual function was not defined
M> E:\source\test\test.cpp(10) : see declaration of 'f'
M>E:\source\test\test.cpp(23) : warning C4259: 'void __thiscall B::f(void)' : pure virtual function was not defined
M> E:\source\test\test.cpp(16) : see declaration of 'f'
M>E:\source\test\test.cpp(23) : error C2556: 'class AB __thiscall B::f(void)' : overloaded function differs only by return type from 'void __thiscall B::f(void)'
M> E:\source\test\test.cpp(16) : see declaration of 'f'
M>E:\source\test\test.cpp(24) : error C2143: syntax error : missing ';' before '}'
M>E:\source\test\test.cpp(24) : error C2143: syntax error : missing ';' before '}'
M>E:\source\test\test.cpp(24) : error C2143: syntax error : missing ';' before '}'
M>Error executing cl.exe.
M>test.exe - 7 error(s), 2 warning(s)
M>
странно, посмотрю вечером на vc6, неужто я ошибся, тогда извеняюсь
"Man feed machine
Machine feed man"
Peter Gabriel — OVO — The Tower That Ate People
Здравствуйте, machine1, Вы писали:
M>Здравствуйте, Аноним, Вы писали:
А>> <skipped>
M>Жалко, хотя по логике должно быть так.. =(
да нельзя так, правильно аноним говорит.
делай с классом прослойкой как тебе уже сказали уже.
Re[7]: множественное наследование и полиморфизм
От:
Аноним
Дата:
22.09.04 10:52
Оценка:
Здравствуйте, Аноним, Вы писали:
А>Еще раз, это не программа на С++. В программе на С++ такого писать нельзя, даже если твой вижуал и скомпилил это, почему — смотри книжки по С++.
А>
А>class AB : public A, public B
А>{
А>public:
А>
А> void A::f() {}
А> void B::f() {}
А>
А>};
А>
Согласен.
Выглядит так, будто к сигнатуре ф-ии добавляется пространство, в котором она объявлена.
Разве это правильно?
Раз у кого-то там это компиляется, попробуйте вызвать ф-ию f() из указателей на базовые классы. Какая из них вызовется. Даже елси вызовы будут правильные, это все равно не есть
good. Такая реализяция не переносима.
Здравствуйте, Аноним, Вы писали:
А>Согласен. А>Выглядит так, будто к сигнатуре ф-ии добавляется пространство, в котором она объявлена. А>Разве это правильно? А>Раз у кого-то там это компиляется, попробуйте вызвать ф-ию f() из указателей на базовые классы. Какая из них вызовется. Даже елси вызовы будут правильные, это все равно не есть А>good. Такая реализяция не переносима.
согласен, проглядел нюанс, vc6 значит ближе к стандарту, чем vc7
"Man feed machine
Machine feed man"
Peter Gabriel — OVO — The Tower That Ate People
Re[9]: множественное наследование и полиморфизм
От:
Аноним
Дата:
22.09.04 11:04
Оценка:
Чего не знаю — того не знаю.
Эта фигня не компилируется в BC++3.0 (только не смейтесь. Это то, что оказалось под рукой.) Так что счет — 2 : 1 — не в пользу VC7
Здравствуйте, Аноним, Вы писали:
А>Чего не знаю — того не знаю. А>Эта фигня не компилируется в BC++3.0 (только не смейтесь. Это то, что оказалось под рукой.) Так что счет — 2 : 1 — не в пользу VC7
в comeau то же
"Man feed machine
Machine feed man"
Peter Gabriel — OVO — The Tower That Ate People
Re[11]: множественное наследование и полиморфизм
От:
Аноним
Дата:
22.09.04 11:10
Оценка:
Еще раз посылаю всех почитать Герба Саттера (Задача о разделении сиамских близнецов),
а про первоначальный вариант забудьте.
Re[12]: множественное наследование и полиморфизм
От:
Аноним
Дата:
22.09.04 11:18
Оценка:
Я вот не пойду читать Саттера, хоть ты меня и призвал. А тебя призову почитать дизайн и эволюция С++, чтоб ты не думал, будто это Саттер изобрел
Re[13]: множественное наследование и полиморфизм
От:
Аноним
Дата:
22.09.04 11:24
Оценка:
Здравствуйте, Аноним, Вы писали:
А>Я вот не пойду читать Саттера, хоть ты меня и призвал. А тебя призову почитать дизайн и эволюция С++, чтоб ты не думал, будто это Саттер изобрел
Я не говорю, что это он изобрел. Я ссылаюсь на то, где об этом прочитал.
Если Страуструп об этом что-то написал — очень хорошо. Можно посмотреть и там.
Re[2]: множественное наследование и полиморфизм
От:
Аноним
Дата:
22.09.04 11:39
Оценка:
Здравствуйте, poilk, Вы писали:
P>Здравствуйте, machine1, Вы писали:
M>>Привет,
M>>незнаю как сделать, хотелось что-то типа этого:
M>>
M>>class A
M>>{
M>>public:
M>> virtual void f() = 0;
M>>};
M>>class B
M>>{
M>>public:
M>> virtual void f() = 0;
M>>};
M>>class AB : public A, public B
M>>{
M>>public:
M>> void A::f() {/*тут реализация*/}
M>> void B::f() {/*тут реализация*/}
M>>}
M>>
P>Смысл виртуального множественного наследования в том, чтобы вызвать нужную функцию в зависимости от типа: P>
P>class A
P>{
P>public:
P> void f(){ cout << "A::f()" << endl;}
P>};
P>class B
P>{
P>public:
P> void f(){ cout << "B::f()" << endl;}
P>};
P>class AB : virtual public A, virtual public B
P>{
P>};
P>int main(int argc, char* argv[])
P>{
P> A *a = new AB;
P> B *b = new AB;
a->>f();
b->>f();
P> return 0;
P>}
P>
P>А смысл чисто виртуальной функции в том, чтобы возложить реализацию на производный класс: P>
P>class A
P>{
P>public:
P> virtual void f() = 0;
P>};
P>class B
P>{
P>public:
P> virtual void f() = 0;
P>};
P>class AB : virtual public A, virtual public B
P>{
P>public:
P> void f() {
P> cout << "f()" << endl;
P> }
P>};
P>int main(int argc, char* argv[])
P>{
P> AB *ab = new AB;
ab->>f();
P> return 0;
P>}
P>
P>Код в вопросе можно поправить так: P>
P>class A
P>{
P>public:
P> virtual void fA() = 0;
P>};
P>class B
P>{
P>public:
P> virtual void fB() = 0;
P>};
P>class AB : public A, public B
P>{
P>public:
P> void fA() {
P> cout << "A::fA()";
P> }
P> void fB() {
P> cout << "B::fB()";
P> }
P>};
P>
P>Или так: P>
P>class A
P>{
P>public:
P> void f(){ cout << "A::f()" << endl;}
P>};
P>class B
P>{
P>public:
P> void f(){ cout << "B::f()" << endl;}
P>};
P>class AB : virtual public A, virtual public B
P>{
P>public:
P> void f() {
P> cout << "AB::f()" << endl;
P> }
P>};
P>int main(){
P> AB *ab = new AB;
ab->>f();
ab->>A::f();
ab->>B::f();
P>}
P>
P>Кстати gnu-шный компиллятор ругается на этот код по-другому: P>
P>error: cannot declare member function `A::f' within `AB'
P>error: cannot declare member function `B::f' within `AB'
Здравствуйте, <Аноним>, Вы писали:
А>Нет, не так. А>Виртуальное наследование предотвращает создание двух экземпларов базового класса.
А>class Base {};
А>class DerA : public Base {}; А>class DerB : public Base {};
А>class DerDer1 : public DerA, public DerB {}; // Данные класса Base бублируюутся. А>class DerDer2 : virtual public DerA, virtual public DerB {}; // А тут вроде нет.
Это верно для такого случая:
Base Base Base
/ \ | |
A B A B
\ / \ /
Derive Derive
согласен.
А>А все варианты, представленные ниже по моему не соответствуют начальной задумке
void f() { f_X();} // Это чтобы больше никто не смог переписать f().
};
Re[2]: множественное наследование и полиморфизм
От:
Аноним
Дата:
22.09.04 12:47
Оценка:
Здравствуйте, poilk, Вы писали:
P>Здравствуйте, machine1, Вы писали:
M>>Привет,
M>>незнаю как сделать, хотелось что-то типа этого:
M>>
M>>class A
M>>{
M>>public:
M>> virtual void f() = 0;
M>>};
M>>class B
M>>{
M>>public:
M>> virtual void f() = 0;
M>>};
M>>class AB : public A, public B
M>>{
M>>public:
M>> void A::f() {/*тут реализация*/}
M>> void B::f() {/*тут реализация*/}
M>>}
M>>
А если так:
int main(int argc, char* argv[])
{
AB* ab = new AB;
A *a = ab;
B *b = ab;
a->f(); b->f(); ab->f(); ?? Зачем тогда вообще нужен AB?
return 0;
}
P>
P>class A
P>{
P>public:
P> void f(){ cout << "A::f()" << endl;}
P>};
P>class B
P>{
P>public:
P> void f(){ cout << "B::f()" << endl;}
P>};
P>class AB : virtual public A, virtual public B
P>{
P>};
P>int main(int argc, char* argv[])
P>{
P> A *a = new AB;
P> B *b = new AB;
a->>f();
b->>f();
P> return 0;
P>}
P>
P>А смысл чисто виртуальной функции в том, чтобы возложить реализацию на производный класс: P>
P>class A
P>{
P>public:
P> virtual void f() = 0;
P>};
P>class B
P>{
P>public:
P> virtual void f() = 0;
P>};
P>class AB : virtual public A, virtual public B
P>{
P>public:
P> void f() {
P> cout << "f()" << endl;
P> }
P>};
P>int main(int argc, char* argv[])
P>{
P> AB *ab = new AB;
ab->>f();
P> return 0;
P>}
P>
А и В — могут представлять собой совершенно разные интерфейсы.
Скажем A — вывод на экран, B — включение дворников у машины.
Значит реализация должна быть у обеих функций: у A::f() и у B::f().
Т.е. такое решение тоже не подходит.
P>Код в вопросе можно поправить так: P>
P>class A
P>{
P>public:
P> virtual void fA() = 0;
P>};
P>class B
P>{
P>public:
P> virtual void fB() = 0;
P>};
P>class AB : public A, public B
P>{
P>public:
P> void fA() {
P> cout << "A::fA()";
P> }
P> void fB() {
P> cout << "B::fB()";
P> }
P>};
P>
Как я уже сказал — не соответствует начальному условию
(одинаковые сигнатуры функций двух разных базовых классав)
P>Или так: P>
P>class A
P>{
P>public:
P> void f(){ cout << "A::f()" << endl;}
P>};
P>class B
P>{
P>public:
P> void f(){ cout << "B::f()" << endl;}
P>};
P>class AB : virtual public A, virtual public B
P>{
P>public:
P> void f() {
P> cout << "AB::f()" << endl;
P> }
P>};
P>int main(){
P> AB *ab = new AB;
ab->>f();
ab->>A::f();
ab->>B::f();
P>}
P>
Не катит.
Должна быть реализована каждая из ф-ий A::f() и B::f().
Причем обращение к ним из указателей на A или B не должно меняться, т.к.
у вы не всегда имеете возможность менять базовые классы.
Короче работает все, но это все — не то, что требовалось.
P>Кстати gnu-шный компиллятор ругается на этот код по-другому: P>
P>error: cannot declare member function `A::f' within `AB'
P>error: cannot declare member function `B::f' within `AB'