构造函数和赋值运算符行为

Constructors and assignment operators behavior

提问人:Inversus 提问时间:7/22/2020 最后编辑:eyllanescInversus 更新时间:7/22/2020 访问量:66

问:

我已经将我的代码带入了工作形式,但还剩下几个问题。 所以代码(这个想法是在数组中可以同时存储一些数据和数据的子数组):

#include <iostream>

using namespace std;

template <typename T>
class Array {

    public:
        Array () {;}
        Array(T const &a) {*this = a;}
        Array(Array const &a) {Resize(SZ+1); M[SZ-1] = a;}
        
        T& operator [] (int i) const {return M[i % SZ];}
        operator T& () {return M[IX % SZ];}
        Array& operator = (T const &a) {
            Resize(SZ+1);
            M[SZ-1] = a;

            return *this;
        }
        Array& operator = (Array const &a)
        {
            Resize(a.SZ);

            if (M != nullptr) {
                for (int i = 0; i < SZ; i++) M[i] = a[i];
            }

            return *this;
        }
        Array<T>& operator = (Array * const p)
        {
            Resize(SZ+1);
            M[SZ-1] = p;
            return *this;
        }

        friend ostream& operator<<(ostream& os, const Array<T> &a)
        {
            for (int i = 0; i < a.SZ; i++) os << a.M[i] << ",";
            return os;
        }

    protected:
        T *M = nullptr;
        int SZ = 0, IX = 0;

    private:
        Array& Resize(int s)
        {
            if (s != 0) {
                int S = SZ;
                if (S > s) S = s;
                T *A = new T[s];

                if (A != nullptr) {
                    int i;
                    for (i = 0; i < S; i++) A[i] = M[i];

                    delete M;
                    M = A;
                    SZ = s;
                }
            } else  {
                delete M;
                SZ = 0;
            }
            return *this;
        }
};

struct S {
    enum class TP {
        INT,
        ARR
    } type;

    int data = 0;
    Array<S> *ptr = nullptr;

    S() {;}
    S(int d) {type = TP::INT; data = d;}
    S(float d) {type = TP::INT; data = d;}
    S(Array<S>* p) {type = TP::INT; ptr = p;}
    int operator = (int d) {type = TP::INT; return data = d;}
    int operator = (float d) {type = TP::INT; return data = d;}
    Array<S>* operator = (Array<S>* p) {type = TP::ARR; return ptr = p;}

    friend ostream& operator << (ostream& os, const S &s)
    {
        switch (s.type) {
            case TP::INT:
                os << s.data;
                break;

            case TP::ARR:
                os << "[" << *s.ptr << "]";
                break;

            default:
                os << "ERROR";
        }
        return os;
    }
};

int main()
{
    Array<S> arr0, *arr1 = new Array<S>;
    arr0 = 10;
    arr0 = 20;
    arr0 = 30;
    *arr1 = 40;
    *arr1 = 50;
    *arr1 = 60;

    arr0 = arr1;

    cout << arr0;

    return 0;
}

现在我将注释掉这些行

S(int d) {type = TP::INT; data = d;}
S(float d) {type = TP::INT; data = d;}
S(Array<S>* p) {type = TP::INT; ptr = p;}
int operator = (int d) {type = TP::INT; return data = d;}
int operator = (float d) {type = TP::INT; return data = d;}
Array<S>* operator = (Array<S>* p) {type = TP::ARR; return ptr = p;}

我将按顺序取消注释它们。 起初,我收到错误消息:

main.cpp:34:错误:没有可行的重载“=” main.cpp:34:错误:'operator=' 不匹配 (操作数类型为“S” 和 'Array* const')

     M[SZ-1] = p;
     ~~~~~~~~^~~
         

到目前为止,一切都很清楚。如果我取消注释该行

S(float d) {type = TP::INT; data = d;}

然后我会收到相同的消息。但是,如果我取消注释该行

S(int d) {type = TP::INT; data = d;}

我收到错误消息:

main.cpp:34: error: invalid conversion from 'Array<S>*' to 'int' [-fpermissive]
             M[SZ-1] = p;
             ~~~~~~~~^~~
         

为什么编译器不尝试将 Array 转换为浮点数,而是尝试将 int 转换为 int ?

然后,我可以删除以下行:

int operator = (int d) {cout << "=int" << endl;type = TP::INT; return data = d;}

一切都会好起来的。然后我认为构造函数和运算符“=”是可以互换的,我可以删除 Array 类中的运算符“=”:

Array& operator = (T const &a) {
    Resize(SZ+1);
    M[SZ-1] = a;
    return *this;
}

但我不能,这会导致错误!但是我可以删除 Array 类构造函数:

Array(Array const &a) {Resize(SZ+1); M[SZ-1] = a;}

这将起作用。相反,如果我删除结构构造函数但保留赋值运算符,则会出现错误。

我有一些猜测,但我很困惑。有人可以清楚地解释为什么会有这种行为吗?

对不起,如果我没有解释清楚。

C++ 构造函数 赋值运算符

评论

2赞 molbdnilo 7/22/2020
摆脱所有隐式转换。他们是邪恶的。

答: 暂无答案