When I run the following code in Microsoft visual studio it outputs junk values (memory addresses?) but when it is run in g++ it outputs what I intend it to (with a few changes like changing srand). How do I fix it to work in visual studio? I only have a few months coding experience and this issue has been bugging me for awhile now.
class Vehicle
{
protected:
int * vin;
double * gasMileage;
public:
Vehicle();
Vehicle(int v, double g);
virtual void display(){cout<<"vin: "<<*vin<<endl<<"gasMileage: " <<*gasMileage<<endl;}
virtual double calcGasUsed(int milesDriven){return *gasMileage * milesDriven;}
int getVin(){return *vin;}
double getGasMileage(){return *gasMileage;}
void changeVin(int newvin) {vin=&newvin;}
void changeGasMileage(double newGasMileage){gasMileage=&newGasMileage;}
void drive();
};
class Suv:public Vehicle
{
protected:
bool *fourWDStatus;
double * fourWDGasMileage;
public:
Suv();
Suv(int v, double g,bool status, double fwdg);
void display();
double calcGasUsed(Suv&, int milesDriven);
bool getFourWDStatus(){return *fourWDStatus;}
double getfourWDGasMileage(){return *fourWDGasMileage;}
void changeFourWDStatus(bool status) {fourWDStatus=&status;}
void changeFourWDGasMileage(double newGasMileage){fourWDGasMileage=&newGasMileage;}
};
Vehicle::Vehicle()
{
this->vin=0000;
this->gasMileage=00;
}
Vehicle::Vehicle(int v, double g)
{
this->vin=&v;
this->gasMileage=&g;
}
Suv::Suv(int v, double g,bool status, double fwdg)
{
this->vin=&v;
this->gasMileage=&g;
this->fourWDStatus=&status;
this->fourWDGasMileage=&fwdg;
}
Suv::Suv()
{
this->vin=0000;
this->gasMileage=00;
this->fourWDStatus=false;
this->fourWDGasMileage=00;
}
void Suv::display()
{
Vehicle::display();
cout<<"fourWDStatus: "<<*fourWDStatus<<endl<<"fourWDGasMileage: "&开发者_开发问答lt;<*fourWDGasMileage<<endl;
}
void Vehicle::drive()
{
int r=rand()%10000;
cout<<calcGasUsed(r)<<endl;
}
double Suv::calcGasUsed(Suv&, int milesDriven)
{
double x;
if (*fourWDStatus== true)
{
x= ((*fourWDGasMileage) * (milesDriven));
return x;
}
else
{
x=((*gasMileage) * (milesDriven));
return x;
}
}
void main()
{
cout << "test";
srand(NULL);
Suv A(300,12.2,false,16.6);
Suv B(200,15.5,false,20.1);
B.changeFourWDStatus(true);
Vehicle C(111,20.5);
C.drive();
C.display();
B.display();
Vehicle arrOfCars[]={A,B,C};
A.drive();
B.drive();
C.drive();
system("pause");
}
You are using pointers without initializing them to anything. A quick look says to me that none of your member variables should be pointers, and none of your constructor arguments should be references. In other places, you assign ints to int*. Did the compiler give you warnings?
Two more bizarre things: why use four-digit 0000
for an integer literal, and why system("pause")
?
Don't store the data members of your class as pointers. There is no need to given your usage. At a glance, I see a problem here:
void changeGasMileage(double newGasMileage){gasMileage=&newGasMileage;}
What this is doing is setting gasMileage to point to a value allocated on the stack. When changeGasMileage
returns, you no longer know what is at that memory location. You could just make gasMileage
a value rather than a pointer. Otherwise, you need to do:
void changeGasMileage(double newGasMileage){gasMileage= new double(newGasMileage);}
The members Vehicle::vin
, Vehicle::gasMileage
as well as Suv::fourWDStatus
and Suv::fourWDGasMileage
are not correctly initialized pointers.
From the code you posted it seems you would be better off by changing them from pointers to regular variables (and adjusting the methods appropriately).
EDIT: If using pointers is a part of assignment, you have to initialize them correctly. This means, in your case, allocating a memory in constructors. It could be this way:
Vehicle::Vehicle()
{
this->vin = new int(0);
this->gasMileage = new double(0.0);
}
Vehicle::Vehicle(int v, double g)
{
this->vin = new int(v);
this->gasMileage = new double(g);
}
Suv::Suv(int v, double g,bool status, double fwdg) : Vehicle(v, g)
{
this->fourWDStatus = new bool(status);
this->fourWDGasMileage = new double(fwdg);
}
Suv::Suv() : Vehicle(0, 0.0)
{
this->fourWDStatus = new bool(false);
this->fourWDGasMileage = new double(0.0);
}
Others have covered the use of pointers as inappropriate for this scenario. I agree.
Also, when the constructor receives a copy - by value - the value you're taking the address of resides on the (call) stack. When that constructor exits, the local variable is destructed (commonly no-op for the builtin types, int, char, float, etc) and accessing them through a pointer is "undefined behavior".
Why it happens like this: Undefined behavior means anything is allowed to happen. Preferrably a compiler diagnostic, alternatively a crash, or worse yet visible as corrupt data, but the worst case it that coincidences have it working until some later time - see also Programming by coincidence.
This area will, once the constructor exits, be open for reuse when calling other functions - they will need a place to store their local variables, parameters, and parameters/return addresses for calling yet other functions.
By some coincidence, gcc (that version, those compiler flags) does not overwrite that place on the stack for printing the values, therefore the values you read are the ones you expect.
精彩评论