Непонятки с using Base::func в производном классе...
От:
Аноним
Дата:
13.12.07 19:07
Оценка:
Иеется код:
class Base
{
public:
protected:
void test();
};
class Derived : public Base
{
public:
using Base::test;
};
int main()
{
using namespace std;
Derived d;
d.test();
vector<Derived> v;
&Derived::test;
for_each(v.begin(), v.end(), mem_fun_ref(&Derived::test));
}
компилятор ругается на выделенных строках на: cannot access protected member declared in class 'Base'.
Объясните плз, в чем трабла?
Re: Непонятки с using Base::func в производном классе...
Здравствуйте, Аноним, Вы писали:
А>Иеется код:
А>компилятор ругается на выделенных строках на: cannot access protected member declared in class 'Base'. А>Объясните плз, в чем трабла?
Мне кажется это баг.
Почему я так думаю — раз был указан access declaration в производном классе, и вызов
d.test();
вполне законен, то и доступ по указателю тоже должен быть. однако это не так в случае MSVC(7.1 и 8-SP1).
class Base
{
public:
protected:
void test(){}
int a;
};
class Derived : public Base
{
public:
using Base::test;
using Base::a;
//Base::a;
};
void mem_fun_test()
{
Derived d;
d.test();
d.a = 10;
int Derived::* pa = &Derived::a;
d.*pa = 100;
void (Derived::* f)() = &Derived::test;
}
результат —
Compiling...
main.cpp
c:\...\main.cpp(31) : error C2248: 'Base::test' : cannot access protected member declared in class 'Base'
c:\...\main.cpp(9) : see declaration of 'Base::test'
c:\...\main.cpp(6) : see declaration of 'Base'
Build log was saved at "file://c:\...\BuildLog.htm"
mem_fun_test — 1 error(s), 0 warning(s)
хотя, если добавить аналогичный код, но не для метода Base, а для его члена, то тут возражений нет, как видно.
к тому же, Comeau Online код успешно скомпилировал.
Your Comeau C/C++ test results are as follows:
Comeau C/C++ 4.3.9 (Mar 27 2007 17:24:47) for ONLINE_EVALUATION_BETA1
Copyright 1988-2007 Comeau Computing. All rights reserved.
MODE:strict errors C++ C++0x_extensions
Re[2]: Непонятки с using Base::func в производном классе...
Здравствуйте, Константин Л., Вы писали:
КЛ>Про стандарт не скажу, но если рассуждать логически, то и на d.test() он тоже должен ругаться
почему он должен на это ругаться ?
Re[2]: Непонятки с using Base::func в производном классе...
От:
Аноним
Дата:
14.12.07 06:16
Оценка:
Здравствуйте, _Dreamer, Вы писали:
_D>Здравствуйте, Аноним, Вы писали:
А>>Иеется код:
А>>компилятор ругается на выделенных строках на: cannot access protected member declared in class 'Base'. А>>Объясните плз, в чем трабла?
_D>Мне кажется это баг. _D>Почему я так думаю — раз был указан access declaration в производном классе, и вызов _D>
_D>d.test();
_D>
_D>вполне законен, то и доступ по указателю тоже должен быть. однако это не так в случае MSVC(7.1 и 8-SP1). _D>[ccode]
я тоже так подумал когда BCB не скомпилил приведенный пример, но когда 2005 и 2008 студия руганулись таким же образом я засомневалси...
Re: Непонятки с using Base::func в производном классе...
Здравствуйте, Аноним, Вы писали:
А>Здравствуйте, dsilence, Вы писали:
D>>Здравствуйте, Аноним, Вы писали:
D>>всё честно. нет объекта — нет синонима.
А>
стандарт. пункт 7.3.3 параграф 13.
Re[4]: Непонятки с using Base::func в производном классе...
Здравствуйте, dsilence, Вы писали:
D>Здравствуйте, Аноним, Вы писали:
А>>Здравствуйте, dsilence, Вы писали:
D>>>Здравствуйте, Аноним, Вы писали:
D>>>всё честно. нет объекта — нет синонима.
А>>
D>стандарт. пункт 7.3.3 параграф 13.
For the purpose of overload resolution, the functions which a introduced by a using-declaration into a derived class will be treated as though they were members of the derived class. In particular, the implicit this parameter shall be treated as if it were a pointer to the derived class rather than to the base class. This has no effect on the type of the function and in all other respects the function remains a member of the base class
пара последних предложений.
Re[5]: Непонятки с using Base::func в производном классе...
От:
Аноним
Дата:
14.12.07 18:51
Оценка:
Здравствуйте, dsilence, Вы писали:
D>>стандарт. пункт 7.3.3 параграф 13.
D>пара последних предложений.
хм, спасибо. т.е. все в соответствии со стандартом...
как же быть тогда? уж и не прикалывает создавать дубли функции в таких случаях... остается сделать открытой в базовом классе...
Re[5]: Непонятки с using Base::func в производном классе...
От:
Аноним
Дата:
14.12.07 19:11
Оценка:
D>>стандарт. пункт 7.3.3 параграф 13.
и получается, что Comeau неправильно компилит?
Re[5]: Непонятки с using Base::func в производном классе...
Здравствуйте, dsilence, Вы писали:
D>>стандарт. пункт 7.3.3 параграф 13.
D>
D>For the purpose of overload resolution, the functions which a introduced by a using-declaration into a derived class will be treated as though they were members of the derived class. In particular, the implicit this parameter shall be treated as if it were a pointer to the derived class rather than to the base class. This has no effect on the type of the function and in all other respects the function remains a member of the base class
D>пара последних предложений.
Объясни, пожалуйста, как эта цитата связана с исходным примером и как она объясняет ошибки компиляции?
Re[6]: Непонятки с using Base::func в производном классе...
Здравствуйте, De Bug, Вы писали:
DB>Здравствуйте, dsilence, Вы писали:
D>>>стандарт. пункт 7.3.3 параграф 13.
D>>
D>>For the purpose of overload resolution, the functions which a introduced by a using-declaration into a derived class will be treated as though they were members of the derived class. In particular, the implicit this parameter shall be treated as if it were a pointer to the derived class rather than to the base class. This has no effect on the type of the function and in all other respects the function remains a member of the base class
D>>пара последних предложений.
DB>Объясни, пожалуйста, как эта цитата связана с исходным примером и как она объясняет ошибки компиляции?
вкратце.
... неявный this должен трактоваться как указатель на дочерний класс, во всех остальных случаях функция остаётся членом базового класса.
&Derived::test;
в данном случае объект не создан соответственно никакого this нет. остаётся вторая часть фразы , что подтверждают ошибки
error C2248: 'Base::test' : cannot access protected member declared in class 'Base'
Re[7]: Непонятки с using Base::func в производном классе...
Вообще-то, этот пункт совсем некстати ты упомянул. Хинт — читай внимательнее, там ясно сказано, для целей разрешения перегрузки. Ничего о доступе к именам тут нет и в помине.
Of course, the code must be complete enough to compile and link.
Re[8]: Непонятки с using Base::func в производном классе...
Здравствуйте, Lorenzo_LAMAS, Вы писали:
L_L>Вообще-то, этот пункт совсем некстати ты упомянул. Хинт — читай внимательнее, там ясно сказано, для целей разрешения перегрузки. Ничего о доступе к именам тут нет и в помине.
А вот и пример, который, по-моему, подходит к сказанному в 7.3.3/13 (в зависимости от наличия/отсутствия закомментированной строки код не компилируется/компилируется):
class A
{
public:
A operator + (const A)const;
};
class B : public A
{
public:
//using A::operator + ;
};
B operator + (const B &, const A &);
int main()
{
A a;
B b;
b + a;
}
Of course, the code must be complete enough to compile and link.
Re[8]: Непонятки с using Base::func в производном классе...
Здравствуйте, Lorenzo_LAMAS, Вы писали:
L_L>Вообще-то, этот пункт совсем некстати ты упомянул. Хинт — читай внимательнее, там ясно сказано, для целей разрешения перегрузки. Ничего о доступе к именам тут нет и в помине.
вот абсолютно легальный код. предлагаю задуматься о том на каком этапе и какая функция будет вызвана. а механизм вызова и почему он именно такой описан как раз в озвученом пункте.
Re[9]: Непонятки с using Base::func в производном классе...
D>вот абсолютно легальный код. предлагаю задуматься о том на каком этапе и какая функция будет вызвана. а механизм вызова и почему он именно такой описан как раз в озвученом пункте.
А я предлагаю не генерить дополнительных примеров, совсем все запутывающих и уводящих все совсем в другую сторону. Я тебе написал ранее пример, который относится к процитированному тобой пункту 7.3.3/13. Для твоего нового примера подходит пункт 7.3.3/12, но все это опять никак не относится к исходному вопросу и твоим обоснованием правильности поведения неправильных компиляторов.
When a using-declaration brings names from a base class into a derived class scope, member functions in
the derived class override and/or hide member functions with the same name and parameter types in a base
class (rather than conflicting). [Example:
struct B {
virtual void f(int);
virtual void f(char);
void g(int);
void h(int);
};
121
ISO/IEC 14882:2003(E) ISO/IEC
7.3.3 The usingdeclaration 7 Declarations
struct D : B {
using B::f;
void f(int); // OK: D::f(int) overrides B::f(int);
using B::g;
void g(char); // OK
using B::h;
void h(int); // OK: D::h(int) hides B::h(int)
};
void k(D* p)
{
p->f(1); //calls D::f(int)
p->f(’a’); //calls B::f(char)
p->g(1); //calls B::g(int)
p->g(’a’); //calls D::g(char)
}
Of course, the code must be complete enough to compile and link.
Re[6]: Непонятки с using Base::func в производном классе...
Здравствуйте, Аноним, Вы писали:
D>>>стандарт. пункт 7.3.3 параграф 13.
А>и получается, что Comeau неправильно компилит?
Нет, не получается. Ибо 7.3.3/13 здесь не к месту.
Of course, the code must be complete enough to compile and link.
Re: Непонятки с using Base::func в производном классе...
The alias created by the using-declaration has the usual accessibility for a member-declaration.
[Example:
class A {
private:
void f(char);
public:
void f(int);
protected:
void g();
};
class B : public A {
using A::f; // error: A::f(char) is inaccessible
public:
using A::g; // B::g is a public synonym for A::g
};
—end example]
Поэтому, пример:
class Base
{
public:
protected:
void test();
};
class Derived : public Base
{
public:
using Base::test;
};
int main()
{
using namespace std;
Derived d;
d.test();
vector<Derived> v;
&Derived::test;
for_each(v.begin(), v.end(), mem_fun_ref(&Derived::test));
}
должен компилиться (ну, при условии, что включены соответствующие заголовки). Например, g++ и Comeau его вполне компилируют.
Of course, the code must be complete enough to compile and link.
Re[2]: Непонятки с using Base::func в производном классе...
Здравствуйте, Lorenzo_LAMAS, Вы писали:
L_L>Вот есть 7.3.3/15, который говорит
L_L>должен компилиться (ну, при условии, что включены соответствующие заголовки). Например, g++ и Comeau его вполне компилируют.
а вот есть 10.3.2 (текст приводить не буду, только код), который говорит что зря они это делают
struct a{
virtual void f();
};
struct b : virtual public a{
virtual void f();
};
struct c : b, virtual a{
using a::f;
};
int main()
{
using namespace std;
с d;
d.f(); //b по стандарту
vector<с> v;
for_each(v.begin(), v.end(), mem_fun_ref(&с::f));//угадайте какая?
}
ладно. спорить можем до бесконечности всё равно ни к чему не приведёт. как выясняется у разработчиков компилеров тоже нет единого мнения.
Re[3]: Непонятки с using Base::func в производном классе...
D>а вот есть 10.3.2 (текст приводить не буду, только код), который говорит что зря они это делают
уффф, этот-то пункт как относится к исходному примеру?
D>
D>struct a{
D> virtual void f();
D>};
D>struct b : virtual public a{
D> virtual void f();
D>};
D>struct c : b, virtual a{
D> using a::f;
D>};
D>int main()
D>{
D> using namespace std;
D> с d;
D> d.f(); //b по стандарту
D> vector<с> v;
D> for_each(v.begin(), v.end(), mem_fun_ref(&с::f));//угадайте какая?
D>}
D>
а::f. а ты как думаешь?
D>ладно. спорить можем до бесконечности всё равно ни к чему не приведёт. как выясняется у разработчиков компилеров тоже нет единого мнения.
Даже у VS нет единого мнения, как он должен себя вести. Например, если в исходном примере заменить все статическими функциями-членами, то &Derived::test ему не нравится, тогда как Derived::test() уже нормально.
Да, к тому же мы по-разному читаем стандарт.
Of course, the code must be complete enough to compile and link.