【问题标题】:Array of structs with base struct returns wrong answer具有基本结构的结构数组返回错误答案
【发布时间】:2014-03-26 23:50:26
【问题描述】:

我的代码给出了错误的答案,所以我将其精简为这一点。 当我的变量arrayCounter=0 时,它会在数组中返回正确答案。 但是当arrayCounter=1时,我得到的错误答案是0。

#include <iostream>
using namespace std;

struct base
{
  int x,y;
};

struct myStruct : base
{
  char c;
  int numOne;
}; myStruct MS[10]; //array of myStruct

base * returnArray(char c)  //function that returns array type
{
  if(c=='m'){ return MS;}
  //I plan to have other structs here similar to myStruct.
}

int main()
{
  MS[0].x=204;   //init 0 value in array
  MS[1].x=97;    //init 1 value in array

  int arrayCounter=0; //count through array. if=0, returns correctly. If=1, then not correct...
  cout<<returnArray('m')[arrayCounter].x<<endl; //MS[1].x=204, MS[1].x=0

  system("pause");
}

【问题讨论】:

    标签: c++ arrays struct return


    【解决方案1】:

    指针算法,包括对数组的索引,是静态的。它不知道您正在访问的对象的动态类型。因此,如果您使用指向派生对象数组的基指针,并尝试递增该指针,您将遇到问题,因为指针算法假定指向的对象确实 is 一个基础对象。

    如果你真的想要数组的多态行为,你必须使用一个指针数组,并使returnArray函数返回base**

    【讨论】:

    • 这听起来很有趣。我试过了,但它不会编译。 base ** 是否返回 *MS,指向 myStruct 的指针?
    • 嗯,您必须将MS 声明为指针数组才能使用这种方法
    • 我对那个方法没问题。所以我做了 myStruct ()MS[10]。和 base(*) 但我得到一个错误。你知道为什么吗?谢谢你的帮助顺便说一句。这个问题我有一段时间了。
    • myStruct MS[10] 不是指针数组。这只是myStruct 对象的数组。
    • "来自myStruct**' to base**'的无效转换"并且'x'没有被声明。我所做的只是进行您建议的那两项更改。奇怪的错误。
    【解决方案2】:

    因为您的函数returnArray() 返回base 的数组,而operator [] 实际上是根据元素大小计算偏移量,如下所示:

    template<typename T>
    T& operator [](T* array, size_t index)
    {
      *(array + sizeof(T) * index);
    }
    

    因此,当您传递base 的数组时,此运算符将计算其大小为sizeof(int) + sizeof(int)。多态性仅适用于指针。所以它会像这样myStruct* a[10] 或者你可以只返回一个 myStruct 数组:myStruct* returnArray();

    还有一件事。如果最终您将创建一个比myStruct 更大的派生类并尝试将其存储在数组中,您将成功,但您将存储的对象将缩小到适合myStruct 的大小,您将丢失数据。

    【讨论】:

      【解决方案3】:

      问题是sizeof(Base)= 8,当returnArray('m')[arrayCounter]中arrayCounter从0增加到1时,地址变8,但是sizeof(myStruct) = 16,地址从16变MS[0] 到 MS[1],如代码所示

      如果你想让这种情况发生,你可以改变指针类型

      cout&lt;&lt;((myStruct*)returnArray('m'))[arrayCounter].x&lt;&lt;endl;

      下面的代码列表输出:

      address of base* array index 0: 0x6013c0
      address of base* array index 1: 0x6013c8
      address of MS array index 0: 0x6013c0
      address of MS array index 1: 0x6013d0
      97
      
      #include <iostream>
      #include <stdio.h>
      using namespace std;
      
      struct base
      {
        int x,y;
      };
      
      struct myStruct : base
      {
        char c;
        int numOne;
      }; myStruct MS[10]; //array of myStruct
      
      base * returnArray(char c)  //function that returns array type
      {
        if(c=='m'){ return MS;}
        //I plan to have other structs here similar to myStruct.
      }
      
      int main()
      {
        MS[0].x=204;   //init 0 value in array
        MS[1].x=97;    //init 1 value in array
      
        int arrayCounter=1; //count through array. if=0, returns correctly. If=1, then not correct...
        printf("address of base* array index 0: %p\n",&returnArray('m')[0]);
        printf("address of base* array index 1: %p\n",&returnArray('m')[1]);
      
        printf("address of MS array index 0: %p\n",&MS[0]);
        printf("address of MS array index 1: %p\n",&MS[1]);
        cout<<((myStruct*)returnArray('m'))[arrayCounter].x<<endl; //MS[1].x=204, MS[1].x=0
      
        return 0;
      }
      

      【讨论】:

        【解决方案4】:

        myStruct* returnArray(char c) 将解决您当前的问题。但是如果你想在你的代码中使用很多派生类,你仍然会感到困惑。

        以下代码可能是更好的选择:

        struct Base
        {
            int x,y;
            int get_x(){
                return x;
            }
        }
        
        cout << MS[arrayCounter].get_x() << endl;
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-10-14
          • 1970-01-01
          • 1970-01-01
          • 2013-08-02
          相关资源
          最近更新 更多