0

Objects (that are not dynamic) are blocks of data in memory.

Is there a way to cycle through and print each item in an object?

I tried doing it with 'this' but I keep getting errors.

#include "stdafx.h"
#include <iostream>
#include "TestProject.h"

using namespace std;


class myclass {

    int someint = 10;
    double somedouble = 80000;
    int somearray[5] = {0, 1, 2, 3, 4};


public:   
    void somefunction();


};


void myclass::somefunction() {


    cout << "\n test \n" << this;

    myclass *somepointer;

    somepointer = this; 

    somepointer += 1;

    cout << "\n test2 \n" << *somepointer;
    //Error: no opperator '<<' matches these operands

}



int main() {


    myclass myobject;

    myobject.somefunction();

    return 0;
}

I'm guessing the error is because the types don't match. But I can't really figure a solution. Is there a dynamic type, or do I have to test the type somehow?

bigcodeszzer
  • 916
  • 1
  • 8
  • 27
  • Unless your class is made entirely of pointers, it is highly unlikely that iterating through memory by 1 is going to get you to the next object. – mjr Oct 21 '15 at 19:58
  • Also... the reason you get "Error: no opperator '<<' matches these operands" is because you don't have a << operator defined for myclass. I'm going to assume that is a compile time error? If you do it to compile, you are going to seg fault or worse when you dereference somepointer. – mjr Oct 21 '15 at 20:01
  • 1
    actually, pointers are larger than a `char` so it wouldn't even work with just pointers. You'd have to have only the likes of `char` – jaggedSpire Oct 21 '15 at 20:01
  • I would also look at this http://stackoverflow.com/questions/15430848/are-class-members-garaunteed-to-be-contiguous-in-memory You are guaranteed "increasing addresses in the order declared". But there is a LOT that you are not guaranteed about your class memory. – mjr Oct 21 '15 at 20:10
  • The idea was to run it in a loop. – bigcodeszzer Oct 21 '15 at 20:11
  • objects are not blocks of data in memory, at least, they should not be thought about in this manner. Thinking this way is the reason for your confusion. – SergeyA Oct 21 '15 at 20:21
  • Adding 1 to a `myclass*` doesn't add 1 to the address stored in the pointer. And it definitely doesn't move to the next member variable. – Bo Persson Oct 21 '15 at 20:22
  • @SergeyA: Actualy it is, but this is error prone to work with it in that manner. – Mykola Oct 21 '15 at 20:25
  • If I were to ever do this, it would be in a context where the data members are fixed and can be tested to a certainty. I'm just curious if its possible, and how. – bigcodeszzer Oct 21 '15 at 20:27
  • and also curious about the difference between structs and classes. Cause I'm pretty sure you /can/ do pointer arithmetic on a struct? – bigcodeszzer Oct 21 '15 at 20:27
  • in class object case can be made some pointer arithmetic too, but you did not do it in right way – Mykola Oct 21 '15 at 20:29
  • so what do you want? – Mykola Oct 21 '15 at 20:30
  • in your case you shift object pointer to entire object size, so it will definitely not a pointer to object member. – Mykola Oct 21 '15 at 20:32
  • Your code is printing long, complicated numbers, not the members. – bigcodeszzer Oct 21 '15 at 20:39
  • @Mykola, i reiterate my point. If you are programming in C++, you should never treat objects as blocks of memory. It would do you no good, and C++ was designed exactly to add abstraction level on top of chunks of memory. – SergeyA Oct 21 '15 at 20:40
  • What I want to do is cycle through the contents of the data, so someint, then somedouble then the elements of somearray. – bigcodeszzer Oct 21 '15 at 20:40
  • Look at my post I shall make some alteration to satisfy you curiosity – Mykola Oct 21 '15 at 20:47
  • @SergeyA - I realize C++ is object oriented, but the language retains a lot of C functionality. I'd say this gives an advantage over other newer oop languages like Java or C# – bigcodeszzer Oct 21 '15 at 20:48
  • @bigcodeszzer, and this is exactly why you have this conondrum. Stop thiking about C++ as an assembly with class keyword. It is not, and it will do you no good to continue in this line of thought. – SergeyA Oct 21 '15 at 20:51
  • I have add what you want. – Mykola Oct 21 '15 at 20:55
  • @SergeyA I disagree. I think code should not be thought exclusively as abstract, even in oop. While most problems can be solved more effectively at an abstract level, others can be solved better at a literal level. The knife cuts both ways. – bigcodeszzer Oct 21 '15 at 20:58
  • @bigcodeszzer: The result code is in the answer below. – Mykola Oct 21 '15 at 21:03

2 Answers2

1

You must add friend global std::ostream operator << to display content of object

#include "stdafx.h"
#include <iostream>

using namespace std;


class myclass {
    int someint;
    double somedouble;
    int somearray[5];
public: 
    myclass()
    {
        someint = 10;
        somedouble = 80000;
        somearray[0] = 0;
        somearray[1] = 1;
        somearray[2] = 2;
        somearray[3] = 3;
        somearray[4] = 4;
    }
    void somefunction();
    friend std::ostream& operator << (std::ostream& lhs, const myclass& rhs);
};


std::ostream& operator << (std::ostream& lhs, const myclass& rhs)
{
    lhs << "someint: " << rhs.someint << std::endl
        << "somedouble: " << rhs.somedouble << std::endl
        << "somearray: { ";

    for (int iIndex = 0; iIndex < 5; iIndex++)
    {
        if (iIndex == 4)
            lhs << rhs.somearray[iIndex] << " }" << std::endl;
        else
            lhs << rhs.somearray[iIndex] <<  ", ";
    }

    return lhs;
}


void myclass::somefunction() {


    cout << "\n test \n" << this;

    myclass *somepointer;

    somepointer = this; 

    somepointer += 1; // wrong pointer to object with `object + sizeof(object)` address, 
    // data probably has been corrupted

    cout << "\n test2 \n" << *somepointer; // displaying objects content
}

int main() {


    myclass myobject;

    myobject.somefunction();

    return 0;
}

as you want to get to the object member using its pointers shifts I post another program

#include "stdafx.h"
#include <iostream>

using namespace std;


#pragma pack (push, 1) // force data alignment to 1 byte

class myclass {
    int someint;
    double somedouble;
    int somearray[5];
public: 
    myclass()
    {
        someint = 10;
        somedouble = 80000;
        somearray[0] = 0;
        somearray[1] = 1;
        somearray[2] = 2;
        somearray[3] = 3;
        somearray[4] = 4;
    }
    void somefunction();
    friend std::ostream& operator << (std::ostream& lhs, const myclass& rhs);
};

#pragma pack (pop) // restore data alignment


std::ostream& operator << (std::ostream& lhs, const myclass& rhs)
{
    lhs << "someint: " << rhs.someint << std::endl
        << "somedouble: " << rhs.somedouble << std::endl
        << "somearray: { ";

    for (int iIndex = 0; iIndex < 5; iIndex++)
    {
        if (iIndex == 4)
            lhs << rhs.somearray[iIndex] << " }" << std::endl;
        else
            lhs << rhs.somearray[iIndex] <<  ", ";
    }

    return lhs;
}


void myclass::somefunction() {

    int* pSomeInt = (int*)this; // get someint address
    double *pSomeDouble = (double*)(pSomeInt + 1); // get somedouble address
    int* pSomeArray = (int*)(pSomeDouble + 1); // get somearray address

    std::cout << "someint: " << *pSomeInt << std::endl
        << "somedouble: " << *pSomeDouble << std::endl
        << "somearray: { ";

    for (int iIndex = 0; iIndex < 5; iIndex++)
    {
        if (iIndex == 4)
            std::cout << pSomeArray[iIndex] << " }" << std::endl;
        else
            std::cout << pSomeArray[iIndex] <<  ", ";
    }
}

int main() {


    myclass myobject;

    myobject.somefunction();

    return 0;
}
Mykola
  • 3,343
  • 6
  • 23
  • 39
  • So you casted the members into variables to print them? – bigcodeszzer Oct 21 '15 at 21:11
  • There are no other method to proper data interpretation for output. – Mykola Oct 21 '15 at 21:15
  • you also may use void or char pointers, than use actual member shifts in bytes to access them i pointer to someint (int*)pObjPrt, pointer to somedouble (double*)(pObjPrt + 4), pointer to somearray (int*)(pObjPrt + 12) – Mykola Oct 21 '15 at 21:20
  • Is there a way to account for padding without packing the data specifically? – bigcodeszzer Oct 21 '15 at 21:27
  • No, there is not. Its because compiler align the data of the class member to the size of member wich has the biggest size in our case its double (8B). so the pointer to somedouble will starts at pObjPrt + 8 instead of pObjPrt + 4, than the address of somearray will starts at pObjPrt + 16 instead of pObjPrt + 12 – Mykola Oct 21 '15 at 21:34
  • So the actual data size will be different, than it is in documentation – Mykola Oct 21 '15 at 21:36
1

C++, by design, has no reflection feature. This means there is no generic, type-independent way to acces type metadata (e.g. the list of members if a class and their types) at runtime. So what you're trying to do (if I understand it correctly) cannot be done in C++.

Also I'm not sure what you meant by "objects (that are not dynamic)". all objects are blocks of data in memory, regardless of whether they are dynamically allocated or not.

  • I agree, but I'm pretty sure dynamic blocks are not guaranteed to be arranged in order. At least, not if they are initialized with 'new' – bigcodeszzer Oct 21 '15 at 20:23