operator =和在C ++中没有继承的函数?

时间:2012-08-17 16:50:17

标签: c++ inheritance operator-overloading crtp

在我刚刚进行的测试之前,我相信只有构造函数不会在C ++中继承。但显然,作业operator=也不是......

  1. 这是什么原因?
  2. 是否有继承赋值运算符的解决方法?
  3. operator+=operator-=,......也是如此吗?
  4. 是否继承了所有其他功能(除了构造函数/运算符=)?
  5. 事实上,我在做一些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>
    {
    };
    

    有没有解决办法让它发挥作用?

    编辑:好的,我已经解决了这个问题。为什么以下不起作用?如何解决问题?

    #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;
    }
    

3 个答案:

答案 0 :(得分:32)

赋值运算符在技术上是继承的;但是,它始终由派生类的显式或隐式定义的赋值运算符隐藏(请参阅下面的注释)。

  

(13.5.3赋值)赋值运算符应由a实现   只有一个参数的非静态成员函数。因为副本   赋值运算符operator=是为类if隐式声明的   用户未声明,基类赋值运算符始终是   由派生类的复制赋值运算符隐藏。

您可以实现一个伪赋值运算符,它只是将调用转发给基类operator=,如下所示:

// 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);
    }
};

答案 1 :(得分:9)

赋值运算符继承的,排序,但......在任何给定的 class,如果没有提供复制赋值运算符,则为编译器 为你生成一个。这意味着您的派生类有效 有一个赋值运算符:

Derived& operator=( Derived const& );

通常的隐藏规则适用;这隐藏了所有的基类 赋值运算符。 (如果基类有赋值运算符 使用此签名,派生类将正常继承它。)

答案 2 :(得分:6)

  1. 您的赋值运算符在技术上是继承的,但它被派生类中的默认复制赋值运算符隐藏。然后,此默认复制分配尝试调用基类的复制分配,该分配不存在,因为您使用自己的分配隐藏它。

  2. 解决此问题的最佳方法是不以非显而易见的方式使用运算符重载(例如,=不代表复制赋值)。在这种情况下,请不要使用operator=:将其称为assignset,然后它将继承并且不会被子副本分配隐藏。

  3. 这些运算符是继承的,没有编译器版本,因此它们永远不会像operator=一样自动隐藏。

  4. 它实际上只是没有继承的构造函数,我想不出任何其他编译器生成的函数可以隐藏父文件中的内容,如operator=

    < / LI>