13

If I have a base class, with only virtual methods and 2 derived classes from the base class, with those virtual methods implemented.

How do I:

 // causes C2259
 BaseClass* base = new BaseClass[2];

 BaseClass[0] = new FirstDerivedClass;
 BaseClass[1] = new SecondDerivedClass;

or:

// causes "base is being used without being initialized"
BaseClass* base;
// causes CC59 again
BaseClass* base = new BaseClass;

base[0] = FirstDerivedClass();
base[1] = SecondDerivedClass();

(or something similar)

...so that I can access the BaseClasss methods through the DerivedClass, but by pointer and the pointer is an array of DerivedClasss?

none
  • 11,793
  • 9
  • 51
  • 87
Deukalion
  • 2,516
  • 9
  • 32
  • 50

5 Answers5

14

Your array is of the wrong type: it stores BaseClass object instances instead of pointers to them. Since BaseClass seems to be abstract, the compiler complains that it cannot default-construct instances to fill your array.

Even if BaseClass were not abstract, using arrays polymorphically is a big no-no in C++ so you should do things differently in any case.

Fix this by changing the code to:

BaseClass** base = new BaseClass*[2];

base[0] = new FirstDerivedClass;
base[1] = new SecondDerivedClass;

That said, most of the time it is preferable to use std::vector instead of plain arrays and smart pointers (such as std::shared_ptr) instead of dumb pointers. Using these tools instead of manually writing code will take care of a host of issues transparently at an extremely small runtime cost.

Jon
  • 428,835
  • 81
  • 738
  • 806
  • 1
    The problem, which is called "object slicing", is not specific to arrays -- it happens any time you assign a derived class to a base class *by value*. E.g. `BaseClass b; b = FirstDerivedClass();` is compilable C++ that nevertheless breaks silently (at best you might get a compiler warning). – j_random_hacker Oct 24 '12 at 12:13
  • Link seems to be moved. – comesuccingfuccslot Mar 14 '17 at 18:35
  • 2
    @Jon You sir, just saved my day. I had declared an array of objects of an inherited class (with virtual functions) and expected it to work. In your answer, however, what does `BaseClass[0] = new FirstDerivedClass;` do? Did you mean `base[0] = new FirstDerivedClass;`? – Aditya Kashi Apr 16 '17 at 21:05
  • Ya I haven't tried this yet, but it seems like is should be base[0]= not BaseClass[0] = . It's array of objects not an array of classes. – user3015682 Nov 13 '19 at 23:51
  • @user3015682 right, fixed. Not sure why it took all of us many years to spot! – Jon Nov 14 '19 at 13:28
6

It is C++ use std::vector instead of simple array:

std::vector<BaseClass*> base;
base.push_back(new FirstDerivedClass());
base.push_back(new SecondDerivedClass());

As Kerrek SB noticed safest method is to use std::unique_ptr:

std::vector<std::unique_ptr<BaseClass> > base;
base.push_back( std_unique_ptr<BaseClass>(new FirstDerivedClass()) );
base.push_back( std_unique_ptr<BaseClass>(new SecondDerivedClass()) );
Denis Ermolin
  • 5,530
  • 6
  • 27
  • 44
2

If your BaseClass contains pure virtual methods, this will fail to compile :

BaseClass* base = new BaseClass[2];

If it doesn't, you are going to get memory leak.

In c++, this is done by using std::vector or std::array, with some kind of smart pointer. For example :

std::vector< std::shared_ptr< BaseClass > > arr( 2 );
arr[0].reset( new FirstDerivedClass() );
arr[1].reset( new SecondDerivedClass() );
BЈовић
  • 62,405
  • 41
  • 173
  • 273
  • An even more important problem with the OP's code is *object slicing*, which breaks programs silently. – j_random_hacker Oct 24 '12 at 12:15
  • @j_random_hacker That is why I suggested to use some kind of smart pointer. Storing objects of base type (if it has no pure functions) would cause slicing – BЈовић Oct 24 '12 at 12:26
0

This was the answer (from Rubby)

BaseClass* Base[2];

Base[0] = new FirstDerivedClass;
Base[1] = new SecondDerivedClass;
Deukalion
  • 2,516
  • 9
  • 32
  • 50
  • 1
    This does something *very* different than what your original code was trying to do. This array is allocated on the stack, while originally it was on the heap. – Jon Oct 24 '12 at 11:45
  • Yes, I guess. Now the array is a pointer and there's pointers in the array. – Deukalion Oct 24 '12 at 12:14
0

Define a pointer array , the pointer type is BaseClass. And assign the pointer to the derivedclass to the elements of the array. just like:

BaseClass* base [2];
base[0] = new FirstDerivedClass;
base[1] = new SecondDerivedClass;
user1203650
  • 300
  • 2
  • 3