首页 > 解决方案 > 静态数组成员在上下文中是私有的

问题描述

我喜欢认为我已经掌握了面向对象编程的大部分方面,但是 C++ 再次给我带来了意想不到的结果。在 C++ 中创建静态数组类(很像 std::array)时,我添加了 + 运算符,它给了我一个非常奇怪的编译器错误。

有没有人遇到过这种情况?

#pragma once

#ifdef NDEBUG
    #define __ESL_Array_AssertCorrectInitSize(array, init)
#else
    #define __ESL_Array_AssertCorrectInitSize(array, init) if (init.size() != array->Size()) throw ESL::ArrayInitializationException("std::initializer_list size is different than static size");
#endif // NDEBUG

#include<cstdint>
#include<utility>
#include<stdexcept>

namespace ESL
{
    class ArrayInitializationException : public std::runtime_error
    {
    public:
        ArrayInitializationException(const std::string &msg): std::runtime_error(msg) {}
    };

    template <typename T, uint32_t S>
    class Array
    {
    public:
        Array(): m_data() {}

        Array(const T (&arr)[S]):
            m_data()
        {
            const T *src_itr = arr;
            T *dst_itr = m_data;

            for (uint32_t i = 0; i < S; ++i)
                *(dst_itr++) = *(src_itr++);
        }

        Array(std::initializer_list<T> list):
            m_data()
        {
            __ESL_Array_AssertCorrectInitSize(this, list)

            const T *src_itr = list.begin();
            T *dst_src = m_data;

            for (uint32_t i = 0; i < S; ++i)
            {
                *(dst_src++) = *(src_itr++);
            }
        }

        Array(const Array &a):
            m_data()
        {
            const T *src_itr = a.m_data;
            T *dst_itr = m_data;

            for (uint32_t i = 0; i < S; ++i)
                *(dst_itr++) = *(src_itr++);
        }

        Array(Array &&a):
            m_data()
        {
            T *src_itr = a.m_data;
            T *dst_itr = m_data;

            for (uint32_t i = 0; i < S; ++i)
                *(dst_itr++) = std::forward<T>(*(src_itr++));
        }

        Array &operator=(const Array &a)
        {
            const T *src_itr = a.m_data;
            T *dst_itr = m_data;

            for (uint32_t i = 0; i < S; ++i)
                *(dst_itr++) = *(src_itr++);
            
            return *this;
        }

        Array &operator=(Array &&a)
        {
            const T *src_itr = a.m_data;
            T *dst_itr = m_data;

            for (uint32_t i = 0; i < S; ++i)
                *(dst_itr++) = std::forward<T>(*(src_itr++));
            
            return *this;
        }

        constexpr uint32_t Size() const { return S; }

        const T &operator[](uint32_t index) const { return m_data[index]; }
        T &operator[](uint32_t index) { return m_data[index]; }

        const T *begin() const { return m_data; }
        T *begin() { return m_data; }
        const T *end() const { return m_data + S; }
        T *end() { return m_data + S; }

        bool operator==(const Array &a) const
        {
            const T *itr1 = m_data;
            const T *itr2 = a.m_data;

            for (uint32_t i = 0; i < S; ++i)
            {
                if (*(itr1++) != *(itr2++)) return false;
            }

            return true;
        }

        bool operator!=(const Array &a) const
        {
            const T *itr1 = m_data;
            const T *itr2 = a.m_data;

            for (uint32_t i = 0; i < S; ++i)
            {
                if (*(itr1++) != *(itr2++)) return true;
            }

            return false;
        }

        template <uint32_t S2>
        Array<T, S + S2> operator+(const Array<T, S2> &a) const
        {
            Array<T, S + S2> res;

            const T *src_itr = m_data;
            T *dst_itr = res.m_data;

            for (uint32_t i = 0; i < S; ++i)
                *(dst_itr++) = *(src_itr++);
            
            src_itr = a.m_data;

            for (uint32_t i = 0; i < S2; ++i)
                *(dst_itr++) = *(src_itr++);

            return res;
        }

    private:
        T m_data[S];
    };
}

如果您需要更多代码,我愿意发布整个文件。我很感激任何意见!谢谢!

编辑:刚刚意识到我忘记了编译器输出:

In instantiation of ‘ESL::Array<T, (S + S2)> ESL::Array<T, S>::operator+(const ESL::Array<T, S2>&) const [with unsigned int S2 = 2; T = double; unsigned int S = 3]’:
[build] /home/joshlengel/Dev/C++/ESL/Main.cpp:10:20:   required from here
[build] /home/joshlengel/Dev/C++/ESL/ESL/include/collection/Array.h:135:30: error: ‘double ESL::Array<double, 5>::m_data [5]’ is private within this context
[build]   135 |             T *dst_itr = res.m_data;
[build]       |                          ~~~~^~~~~~
[build] /home/joshlengel/Dev/C++/ESL/ESL/include/collection/Array.h:149:11: note: declared private here
[build]   149 |         T m_data[S];

标签: c++

解决方案


原因是针对类的,Array<double, 2>而且Array<double, 3>是完全不同的两个类。这就是为什么它说你不能访问私人成员。为此,您要么必须m_data公开成员,要么begin()像这样使用,

template <uint32_t S2>
Array<T, S + S2> operator+(const Array<T, S2>& a) const
{
    Array<T, S + S2> res;

    // You can ditch the for loops and use std::copy instead. It *can* be more efficient.
    std::copy(begin(), end(), res.begin());
    std::copy(a.begin(), a.end(), res.begin() + S);

    return res;
}

推荐阅读