如何使用struct作为接口从函数返回指向数组的指针

时间:2014-08-22 01:42:24

标签: c++ arrays pointers struct interface

我正在尝试用C ++创建一个数组接口。


在下面的代码中 tmpClass[1].GetA()返回“w” tmpInterface[1]会导致错误
有没有办法定义一个接口,以便它可以访问数组的元素?
如何让tmpInterface表现得像tmpClass

struct IA
{
    virtual char GetA() = 0;
    virtual void SetA(char pA) = 0;
};

class A:public IA
{
    public:
        A(){ var = 0; }
        A(char pVar){ var = pVar; }
        char GetA(){ return var; }
        void SetA(char pA){ var = pA; }
    private:
    int var;
};

class B
{
    public:
        B(){ 
            mA[0].SetA('c');
            mA[1].SetA('w');
            mA[2].SetA('6');
            mA[3].SetA('$');
        }

        int GetCount(){}
        IA* Get1(){ return mA; }
        A* Get2(){ return mA; }
    protected:
        A mA[4];
};


int main()
{
    B mainClass;
    IA *tmpInterface = mainClass.Get1();
    A *tmpClass = mainClass.Get2();

    for (int i = 0; i < 4; i++)
    {
        //once i>0 then tmpInterface no longer points to a valid character
        //and program crashes
        System::Console::Write(
            "A = "+tmpClass[i].GetA()+
            " IA = "+tmpInterface[i].GetA()); 
    }
    return 0;
}

4 个答案:

答案 0 :(得分:0)

下标运算符使用指针运算,并且对类型与其指向的对象的实际类型不同的指针执行指针运算是未定义的行为。 §5.7[expr.add] / p7:

  

对于加法或减法,如果表达式PQ具有类型   “指向cv T”的指针,其中T与cv-nonqualified不同   数组元素类型,行为未定义。 [注意:在   特别是,指向基类的指针不能用于指针   当数组包含派生类类型的对象时的算术运算。    - 结束记录]

因此,要索引A s数组,您需要A*。如果你只想使用IA,那么你需要应用一些程序员的灵丹妙药 - 间接。返回IA **指向IA *数组的第一个元素,其成员均指向A

答案 1 :(得分:0)

请注意,多态只适用于指针或对类实例的引用,而不是直接与实例一起使用。这是你问题的根源。

您可以考虑使用std::vector<A*>而不是数组。

答案 2 :(得分:0)

在有效的C ++中,它表示不要在数组上使用多态; 您可以添加类似operator []的虚函数,例如:

struct IA
{
    //...
    virtual IA* Offset(int index)
    {
        return this + index;
    }
};

class A:public IA
{
public:
    //...
    virtual A* Offset(int index)
    {
        return this + index;
    }
};

然后它运作正常。

cout << "A = " << tmpClass->Offset(i)->GetA();
cout << " IA = " << tmpInterface->Offset(i)->GetA() << endl;

此外,什么是C ++中的System :: Console :: Write?

答案 3 :(得分:0)

B类型的对象中,您有一组A个对象。在成员函数B::Get1()B::Get2()中返回指向数组的第一个元素的指针。

让我们说阵列的布局是:

+--------------+--------------+--------------+--------------+
|    mA[0]     |    mA[1]     |    mA[2]     |    mA[3]     |         
+--------------+--------------+--------------+--------------+

执行时

IA *tmpInterface = mainClass.Get1();
A *tmpClass = mainClass.Get2();

tempInterfacetmpClass指向mA的第一个元素。

+--------------+--------------+--------------+--------------+
|    mA[0]     |    mA[1]     |    mA[2]     |    mA[3]     |         
+--------------+--------------+--------------+--------------+
^
| 
tmpInterface as well as tmpClass

当您在tmpInterfacetmpClass上进行算术运算时,您会看到非常不同的结果。

tmpInterface+1tmpClass+1指向哪里?

+--------------+--------------+--------------+--------------+
|    mA[0]     |    mA[1]     |    mA[2]     |    mA[3]     |         
+--------------+--------------+--------------+--------------+
      ^        ^
      |        | 
      |        tmpClass+1
      tmpInterface+1

由于tmpClass的类型为A*tmpClass+1指向数组中的下一个对象。但是,由于tmpInterface的类型为IA*,而sizeof(IA)sizeof(A)不同,tmpInterface+1指向中间的某些内容。它没有指向IA类型的对象。如果您尝试将tmpInterface+1作为IA*进行访问,则会出现未定义的行为。