todas - operator=y funciones que no son heredadas en C++?
todas las funciones de c++ (3)
Su operador de asignación es heredado técnicamente, pero luego está oculto por el operador de asignación de copia predeterminado en la clase derivada. Esta asignación de copia predeterminada intenta llamar a la asignación de copia de la clase base que no existe ya que la ocultó con su propia tarea.
La mejor manera de resolver esto es no utilizar la sobrecarga del operador de forma no obvia (
=
no significa asignación de copia, por ejemplo). En este caso, no useoperator=
: llámelo algo así comoassign
oset
y luego heredará y no se ocultará por la asignación de copia secundaria.Estos operadores son heredados y no hay versiones compiladas, por lo que nunca se ocultan automáticamente como
operator=
.Realmente solo son constructores que no son heredados, y no puedo pensar en ninguna otra función generada por el compilador que pueda ocultar algo del padre como en
operator=
.
Hasta una prueba que acabo de hacer, creía que solo los constructores no se heredaban en C ++. Pero aparentemente, el operator=
asignación operator=
no es demasiado ...
- ¿Cuál es la razón de eso?
- ¿Hay alguna solución alternativa para heredar el operador de asignación?
- ¿Es también el caso para
operator+=
,operator-=
, ...? - ¿Se heredan todas las otras funciones (aparte de los constructores / operator =)?
De hecho, me encontré con este problema ya que estaba haciendo algo de CRTP:
template<class Crtp> class Base
{
inline Crtp& operator=(const Base<Crtp>& rhs) {/*SOMETHING*/; return static_cast<Crtp&>(*this);}
};
class Derived1 : public Base<Derived1>
{
};
class Derived2 : public Base<Derived2>
{
};
¿Hay alguna solución para que funcione?
EDITAR: OK, he aislado el problema. ¿Por qué lo siguiente no está funcionando? Como resolver el problema ?
#include <iostream>
#include <type_traits>
// Base class
template<template<typename, unsigned int> class CRTP, typename T, unsigned int N> class Base
{
// Cast to base
public:
inline Base<CRTP, T, N>& operator()()
{
return *this;
}
// Operator =
public:
template<typename T0, class = typename std::enable_if<std::is_convertible<T0, T>::value>::type>
inline CRTP<T, N>& operator=(const T0& rhs)
{
for (unsigned int i = 0; i < N; ++i) {
_data[i] = rhs;
}
return static_cast<CRTP<T, N>&>(*this);
}
// Data members
protected:
T _data[N];
};
// Derived class
template<typename T, unsigned int N> class Derived : public Base<Derived, T, N>
{
};
// Main
int main()
{
Derived<double, 3> x;
x() = 3; // <- This is OK
x = 3; // <- error: no match for ''operator='' in '' x=3 ''
return 0;
}
El operador de asignación es heredado, más o menos, pero ... En cualquier clase dada, si no proporciona un operador de asignación de copia, el compilador genera uno para usted. Eso significa que sus clases derivadas tienen efectivamente un operador de asignación:
Derived& operator=( Derived const& );
Y las reglas de ocultación usuales se aplican; esto oculta a todos los operadores de asignación de la clase base. (Si la clase base tenía un operador de asignación con esta firma, la clase derivada lo heredaría normalmente).
El operador de asignación es técnicamente heredado; sin embargo, siempre está oculto por un operador de asignación explícita o implícitamente definido para la clase derivada (ver comentarios a continuación).
(13.5.3 Asignación) Un operador de asignación se implementará mediante una función de miembro no estático con exactamente un parámetro. Debido a que un operador de asignación de copia
operator=
se declara implícitamente para una clase si el usuario no lo declara, un operador de asignación de clase base siempre está oculto por el operador de asignación de copia de la clase derivada.
Puede implementar un operador de asignación ficticio que simplemente reenvía la llamada al operator=
clase base operator=
, de esta manera:
// Derived class
template<typename T, unsigned int N> class Derived : public Base<Derived, T, N>
{
public:
template<typename T0, class = typename std::enable_if<std::is_convertible<T0, T>::value>::type>
inline Derived& operator=(const T0& rhs)
{
return Base<Derived, T, N>::operator=(rhs);
}
};