template<typename _Tp>
class aa
{
_Tp* _d;
public:
aa& operator= (_Tp* d) { _d=d; return *this; }
};
class bb : public aa<int>
{
};
int main ()
{
aa<int> a;
bb b;
int val = 5;
a = &val;
b = &val;
}
Компилятор на строке "b = &val;" естественно выдает ошибку "Could not find a match for 'bb::operator =(int *)' in function main()". Объяснение этому факту в стандарте (если я ошибаюсь — поправьте):
13.5.3 Assignment [over.ass]
1 An assignment operator shall be implemented by a non-static member
function with exactly one parameter. Because a copy assignment opera-
tor operator= is implicitly declared for a class if not declared by
the user (_class.copy_), a base class assignment operator is always
hidden by the copy assignment operator of the derived class.
Вопрос: Как это обойти? Т.е. хочется определить в базовом классе оператор присваивания, а во всех дочерних им пользоваться.
Вариант
typedef aa<int> bb;
не подходит, т.к. bb может содержать дополнительные методы.
Здравствуйте PaulV, Вы писали:
PV>Столкнулся со следущей проблемой: PV>
PV>template<typename _Tp>
PV>class aa
PV>{
PV> _Tp* _d;
PV>public:
PV> aa& operator= (_Tp* d) { _d=d; return *this; }
PV>};
PV>class bb : public aa<int>
PV>{
PV>};
PV>int main ()
PV>{
PV> aa<int> a;
PV> bb b;
PV> int val = 5;
PV> a = &val;
PV> b = &val;
PV>}
PV>
PV>Компилятор на строке "b = &val;" естественно выдает ошибку "Could not find a match for 'bb::operator =(int *)' in function main()". Объяснение этому факту в стандарте (если я ошибаюсь — поправьте): PV> PV>13.5.3 Assignment [over.ass]
PV>1 An assignment operator shall be implemented by a non-static member PV> function with exactly one parameter. Because a copy assignment opera- PV> tor operator= is implicitly declared for a class if not declared by PV> the user (_class.copy_), a base class assignment operator is always PV> hidden by the copy assignment operator of the derived class. PV>
PV>Вопрос: Как это обойти? Т.е. хочется определить в базовом классе оператор присваивания, а во всех дочерних им пользоваться.
PV>Вариант PV>
PV>typedef aa<int> bb;
PV>
PV>не подходит, т.к. bb может содержать дополнительные методы.
PV>Заранее спасибо!
Видимо надо написать так:
class bb : public aa<int>
{
public:
using aa<int>::operator=;
};
Но MS Visual C++ .NET этого не понимает и продолжает ругаться
Здравствуйте PaulV, Вы писали:
PV>Столкнулся со следущей проблемой: PV>
PV>template<typename _Tp>
PV>class aa
PV>{
PV> _Tp* _d;
PV>public:
PV> aa& operator= (_Tp* d) { _d=d; return *this; }
PV>};
PV>class bb : public aa<int>
PV>{
PV>};
PV>int main ()
PV>{
PV> aa<int> a;
PV> bb b;
PV> int val = 5;
PV> a = &val;
PV> b = &val;
PV>}
PV>
PV>Компилятор на строке "b = &val;" естественно выдает ошибку "Could not find a match for 'bb::operator =(int *)' in function main()". Объяснение этому факту в стандарте (если я ошибаюсь — поправьте): PV> PV>13.5.3 Assignment [over.ass]
PV>1 An assignment operator shall be implemented by a non-static member PV> function with exactly one parameter. Because a copy assignment opera- PV> tor operator= is implicitly declared for a class if not declared by PV> the user (_class.copy_), a base class assignment operator is always PV> hidden by the copy assignment operator of the derived class. PV>
Объяснение этому факту очень простое: операторы не наследуются.
PV>Вопрос: Как это обойти? Т.е. хочется определить в базовом классе оператор присваивания, а во всех дочерних им пользоваться.
Можно определять операторы присваивания в дочерних классах, а в имплементации приводить операнды к родителю и, соответственно, вызывать оператор присваивания у родителя.
Здравствуйте Alik, Вы писали:
A>Объяснение этому факту очень простое: операторы не наследуются.
Не "операторы не наследуются", а видимость оператор= перекрывается либо указываемым явно оператором= в дочернем классе либо генерируемым по умолчанию, если таковой не указан. Поэтому он не виден.
Точно так же как перекрываются все перегруженные функции базового класса при указании хотя бы одной с таким именем в дочернем.
Измени в примере = на < (семантика не волнует пока), и ошибки не получишь.
Здравствуйте Vi2, Вы писали:
Vi2>Здравствуйте Alik, Вы писали:
A>>Объяснение этому факту очень простое: операторы не наследуются.
Vi2>Не "операторы не наследуются", а видимость оператор= перекрывается либо указываемым явно оператором= в дочернем классе либо генерируемым по умолчанию, если таковой не указан. Поэтому он не виден.
Vi2>Точно так же как перекрываются все перегруженные функции базового класса при указании хотя бы одной с таким именем в дочернем.
Согласен, формулировка не точная. Выдернутая из контекста она вообще получает свой достаточно общий и уже некорректный смысл. Но результат — что в лоб, что по лбу. Скажем так: поскольку для любого класса генерируется свой оператор присваивания (и это поведение компилятора вполне соответствует стандарту), класс наследник всегда имеет свои оператор присваивания, отличный от родительского.
Здравствуйте Alik, Вы писали:
A> Согласен, формулировка не точная. Выдернутая из контекста она вообще получает свой достаточно общий и уже некорректный смысл. Но результат — что в лоб, что по лбу. Скажем так: поскольку для любого класса генерируется свой оператор присваивания (и это поведение компилятора вполне соответствует стандарту), класс наследник всегда имеет свои оператор присваивания, отличный от родительского.
Но,как верно заметил dupamid, operator = из базового класса можно вытащить через using.
Здравствуйте DarkGray, Вы писали:
DG>Но,как верно заметил dupamid, operator = из базового класса можно вытащить через using.
Не вижу смысла его вытаскивать
Он всё равно вызовется — при генерации operator= сначала вызывается operator= для всех базовых классов, а затем — для всех member-ов, добавленных в этом классе
Здравствуйте Ридош Вадим, Вы писали:
DG>>Но,как верно заметил dupamid, operator = из базового класса можно вытащить через using.
РВ>Не вижу смысла его вытаскивать РВ>Он всё равно вызовется — при генерации operator= сначала вызывается operator= для всех базовых классов, а затем — для всех member-ов, добавленных в этом классе
Так operator = не всегда же определяет конструктор копии... Так в примере из начального письма было видно, что в данном случае operator = выступает в качестве operator-а "преобразования" из int-а в класс
Здравствуйте Ридош Вадим, Вы писали:
DG>>Но,как верно заметил dupamid, operator = из базового класса можно вытащить через using.
РВ>Не вижу смысла его вытаскивать РВ>Он всё равно вызовется — при генерации operator= сначала вызывается operator= для всех базовых классов, а затем — для всех member-ов, добавленных в этом классе
Речь идет об операторе присваивания из постороннего указательного типа, а не о копирующем операторе присваивания.