6

I am writing a program for a pointer to a Derived class.Here is my code,

 #include <iostream>
    using namespace std;

    class base {
      int i;
    public:
      void set_i(int num) { i=num; }
      int get_i() { return i; }
    };

    class derived: public base {
      int j;
    public:
      void set_j(int num) {j=num;}
      int get_j() {return j;}
    };

    int main()
    {
      base *bp;
      derived d[2];

      bp = d;

      d[0].set_i(1);
      d[1].set_i(2);

      cout << bp->get_i() << " ";
      bp++; 
      cout << bp->get_i(); 

      return 0;
    }

The program is displaying 1 correct value and other garbage value because

bp++;

is incrementing the pointer to point to next object of class base type but not of class derived type.

we can display answer correctly by writing

> bp =& d[0];   
bp1=&d[1];  
 d[0].set_i(1);  
 d[1].set_i(2);

but then we have to assign 2 pointers .Similarly if we have to take 100 values then we have to assign 100 pointers.That is not good.

My question is that can we show the value of array by single pointer ?

Freedom911
  • 610
  • 2
  • 12
  • 26
  • 2
    Why are you using a pointer to base and not to the real type? – David Rodríguez - dribeas Aug 30 '13 at 19:38
  • I didn't get you.Please could you tell more? – Freedom911 Aug 30 '13 at 19:41
  • 1
    Pointer arithmetic is founded on the premise of a memory address and a type-size. The type size is based on the fundamental type of the pointer. This is doing exactly what you're telling it to. Advancing the address value in the `base` pointer `bp1`by its type-size (the size of a `base`; not the size of a `derived`). If you want a pointer to the second element, you'll have to address the element you want (ex: `bp1 = d+1;`) – WhozCraig Aug 30 '13 at 19:42
  • 1
    @MsFreedom911: The question is simple, why do you want to use a `base*` instead of a `derived*`? – David Rodríguez - dribeas Aug 30 '13 at 19:44
  • 1
    You have already pretty much answered your own question. If you must declare and use bp as a pointer to the base class, you could "increment" it by indexing directly into the array: `int i = 0; ... bp = &d[i]; i++` – Dan Breslau Aug 30 '13 at 19:45
  • @ David Rodríguez - dribeas I got your point – Freedom911 Aug 30 '13 at 19:46

5 Answers5

7

I imagine the reason OP is trying to do this is so that he can have an array of objects which can be arbitrary derived instances of some base class, and iterate over them. If this is the case, you really need an array of pointers to your base class. Something like:

class Base { /* ... */ };
class Derived1 : public Base { /* ... */ };
class Derived2 : public Base { /* ... */ };

// ...

Base *arr[10] = {new Derived1(), new Derived1(), new Derived2(), ...};

// ...

for(Base **p = arr; p < arr+10; ++p) {
  *p->foo();
  // ...
}

If I guessed OP's real problem, I think this would solve it.

Nicu Stiurca
  • 8,747
  • 8
  • 40
  • 48
  • 1
    @MsFreedom911 Glad to hear it. For completeness, I would also recommend that instead of plain arrays you use vectors and instead of raw pointers you use smart pointers to guard against memory leaks. – Nicu Stiurca Aug 30 '13 at 19:54
  • 1
    Although I don't know what are smart pointer and vectors ,because I have just started learning c++.I will google it.Thanks for the advice – Freedom911 Aug 30 '13 at 19:57
  • 1
    @MsFreedom911 If you are following some kind of tutorial, then it hopefully has some exposure to them (at least if it's a good tutorial!). Be aware that smart pointers in C++03 (the old C++ standard) are rather half baked unless you use an external library like Boost. Since you are learning, I think you might as well learn the new standard (C++11) directly--unless you have some compelling reason not to--which has excellent built-in smart pointers. Also, be sure to check out [The Definitive C++ Book Guide and List](http://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list). – Nicu Stiurca Aug 30 '13 at 20:04
  • 2
    While vectors would be good; I would suggest actually LEARNING how to manage your memory first since you are LEARNING the language before jumping to using smart pointers. Two reasons: 1. you'll appreciate them properly when you use them 2. you'll understand what they are taking care of for you. i.e. Learn Calculus before you use a calculator to derive the answer for you. Just throwing a lot of third party solutions at every problem is more than needed and only helps to complicate the debugging for someone who doesn't know what they are yet doing. – UpAndAdam Aug 30 '13 at 20:41
  • @UpAndAdam: They said the same thing about assembly code and compilers, but I did pretty well learning a few compiled languages first and x86 opcodes later. – aschepler Aug 30 '13 at 22:15
  • @aschepler True, I wouldn't suggest going that far to start. IME (and obviously this is a generalization) from visiting schools on recruiting trips giving technical interviews, the folks who came up on 'Java-based' curriculum who learn C later seem to consistently lack understanding surrounding memory management which has hampered them when they come over to HPC and performance oriented C/C++. If that's not a concern have at it and go search here for debates on best smart pointer classes :-) – UpAndAdam Sep 03 '13 at 14:12
3

You can not do what your are attempting to do.

You are creating an array of objects which are of the derived size. When you use a base pointer to an array you are attempting to move the pointer by the size of the base. If you had an array of Derived * then you could point to them with a base * * and everything would work. If you have actual objects you must use the correct data type.

The only reason you would want to accomplish this is to utilize the polymorphic features of a base class. Polymorphism only works on pointers and refrecnes any way so storing the actually object buys you little.

rerun
  • 25,014
  • 6
  • 48
  • 78
2

If you insist on using base class pointer for pointing derived class you could not use ++ for iterate. you should do this:

bp = d;
.
.
.
bp = &d[1];
Aryan
  • 2,675
  • 5
  • 24
  • 33
1

In C/C++/ObjectiveC, sizes are always implicit. For a single type, the compiler knows what size it is, likewise it knows the size of the object a pointer is pointing to only by the type of that pointer. Accordingly, incrementing a pointer is always adding a compile time constant to the pointer; it cannot be different because there is no such thing as a size stored anywhere in memory. So whenever you cast a pointer from one class to another, you must not use pointer arithmetic on it anymore, otherwise you get undefined behaviour.

As a solution, go with ShighShagh's answer and use an array of pointers.

cmaster - reinstate monica
  • 38,891
  • 9
  • 62
  • 106
1
  • In C++ you can use a pointer as an array, to store objects of different kinds.
  • To create an array pointer you simply declare the pointer variable and allocate memory by using either MALLOC or NEW. So you would have;
  • base *bp = (base *)malloc(sizeof(10)/sizeof(base));
  • This will create a pointer array of size 10. You can then use this pointer to store the base object or derived object. And you can also use a for loop to iterate through the pointer of 10 elements.
Juniar
  • 1,269
  • 1
  • 15
  • 24