954,505 Members — Technology Publication meets Social Media
Username:
Password:
Lost login information?
Have something to say? Contribute New Article Reply to this Article

Help with dynamic_cast & array of pointers

I'm having trouble with the (dynamic_cast(vptr[k])) -> DOTLicense() part.

If my numOfVehicles = 1 it works fine, but if numOfVehicles > 1 I get core dump error. I can remove the dynamic_cast statement and it works for numOfVehicles > 1. Any help or advise on what I'm doing wrong is appreciated.

int main()
{

  const size_t maxNumOfVehicles(100);
  const size_t maxSnSize(20);
  const size_t maxDotSize(20);
  size_t numOfVehicles;

  std::cout << "Tracker started..." << std::endl;

  // get the number of vehicles
  std::cin >> numOfVehicles;

  // Create an array of vehicle pointers
  Vehicle* vptr[maxNumOfVehicles];
  VehicleType v;  // used to return an enum value
  char sn [maxSnSize];
  unsigned int passengerCap;
  char dotLicense[maxDotSize];
  float d1;
  float d2;
  float d3;

  while((numOfVehicles != 0) && (numOfVehicles < maxNumOfVehicles)) // Begin
    { 
    
      // Process the vehicle segment
      for(size_t i=0;i<numOfVehicles;++i) // Begin first for loop
	{

	  // get the vehicle serial number and check it
	  std::cin >> std::setw(maxSnSize) >> sn;
	  v = Vehicle::SnDecode(sn);
	  if(v == badSn) break; // don't process - can't make vehicle object

	  // get the passenger capacity
	  std::cin >> passengerCap;
	  
	  switch(v) // Begin switch
	    {
	    case vehicle:
	      vptr[i] = new Vehicle(sn, passengerCap);
	      break;
	    case car:
	      vptr[i] = new Car(sn, passengerCap);
	      break;
	    case truck:
	      std::cin >> std::setw(maxDotSize) >> dotLicense;
	      vptr[i] = new Truck(sn, passengerCap, dotLicense);
	      break;
	    case van:
	      std::cin >> std::setw(maxDotSize) >> dotLicense;
	      std::cin >> d1;
	      std::cin >> d2;
	      std::cin >> d3;
	      vptr[i] = new Van(sn, passengerCap, dotLicense, d1, d2, d3);
	      break;
	    case tanker:
	      std::cin >> std::setw(maxDotSize) >> dotLicense;
	      std::cin >> d1;
	      std::cin >> d2;
	      vptr[i] = new Tanker(sn, passengerCap, dotLicense, d1, d2);
	      break;
	    case flatbed:
	      std::cin >> std::setw(maxDotSize) >> dotLicense;
	      std::cin >> d1;
	      std::cin >> d2;
	      vptr[i] = new Flatbed(sn, passengerCap, dotLicense, d1, d2);
	      break;
	    default:
	      std::cerr << "**Error: bad serial number passed to decision logic\n";
	      break;
	    } // end switch


	} // end first for loop            

	  // Send Report to Std. Output
	      std::cout << "Type  Pass Cap  Load Cap  DOT License  Serial Number\n";
	      std::cout << "----  --------  --------  -----------  -------------\n";
	      
	  for(size_t k=0;k<numOfVehicles;++k) // begin second for loop
	    {

	      if(truck <= v) // begin if statement
		{
		  std::cout << " " << vptr[k] -> ShortName() << "         " << vptr[k] -> PassengerCapacity() << "      " << vptr[k] -> LoadCapacity() << "  " << (dynamic_cast<Truck*>(vptr[k])) -> DOTLicense() << "  " <<  vptr[k] -> SerialNumber() << "\n";
		}
	      else
		{
		  std::cout << " " << vptr[k] -> ShortName() << "         " << vptr[k] -> PassengerCapacity() << "      " << vptr[k] -> LoadCapacity() << "  (NA)  " <<  vptr[k] -> SerialNumber() << "\n";
		} // end if statement

	      delete vptr[k];
	    } // end second for loop


      // Finished processing vehicle segment. Wait for next segment.
      std::cout << "Tracker started..." << std::endl;
      std::cin >> numOfVehicles;

          } // end while loop

  // Bye Bye message
  std::cout << "...Thank you for using Tracker.\n";

  return 0;
}
Dee76
Newbie Poster
6 posts since Aug 2004
Reputation Points: 10
Solved Threads: 0
 

Hard to say without a better idea of how your different classes relate to one another.

What type is vptr for example?

Separating the code into two functions
- input data
- print data
would help with following what's going on.

Salem
Posting Sage
Team Colleague
11,531 posts since Dec 2005
Reputation Points: 5,862
Solved Threads: 953
 
if(truck <= v) // begin if statement
        {
          ... (dynamic_cast<Truck*>(vptr[k])) -> DOTLicense() ...
        }
          else
        {
          ...
        } // end if statement


the dynamic_cast operator in c++ is a run-time cast operator; the corrctness of the result of the cast is guaranteed by the implementation if the cast succeeds. if it fails, the result of a dynamic cast on a pointer is a zero pointer. and if you try to use the result without checking for succeess, a failed cast will cause unpleasant things to happen; typically a core dump.
assuming that the variable v has the right value of the VehicleType enum, if( truck <= v ) would be true for things other than a truck. and if that happens, (dynamic_cast<Truck*>(vptr[k])) would result in a zero pointer which you are trying to dereference. that the failure occurs at precisely the second element of the array is probably because you are using the same inputs every time to test your code. to debug the current code, print out the following:

Truck* pointer = (dynamic_cast<Truck*>(vptr[k])) ;
std::cout << "pointer: " << pointer 
                 << "  type of object: " << typeid( *(vptr[k]) ).name() << '\n' ;



unless you are trying to learn about dynamic_casts, consider using virtual functions instead of the type variable and casts.

vijayan121
Posting Virtuoso
1,606 posts since Dec 2006
Reputation Points: 1,159
Solved Threads: 287
 

This article has been dead for over three months

Post: Markdown Syntax: Formatting Help
You