2011-08-07 2 views
0

Microsoft Visual Studio에서 다음 코드를 실행하면 정크 값 (메모리 주소)이 출력되지만 g ++에서 실행되면 srand 변경과 같은 몇 가지 변경 사항이 있음). Visual Studio에서 작동하도록 수정하려면 어떻게해야합니까? 나는 경험을 코딩하는 데 몇 달 밖에 안 남았고,이 문제는 지금 당장 나를 괴롭혔다.Visual Studio에서 C++ 포인터에 문제가 발생했습니다 (g ++에서 작동).

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: "<<*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"); 

} 

답변

1

회원 Vehicle::vin, Vehicle::gasMileage뿐만 아니라 Suv::fourWDStatusSuv::fourWDGasMileage가 제대로 초기화되지 않은 포인터를.

게시 한 코드에서 포인터를 일반 변수로 변경하고 적절하게 조정하는 것이 더 나을 것 같습니다.

편집 : 포인터가 할당의 일부인 경우 올바르게 초기화해야합니다. 이는 사용자의 경우 생성자에서 메모리를 할당한다는 의미입니다. 이 방법이 될 수 있습니다.

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); 
} 
+0

이 데이터 멤버에 대한 포인터를 사용해야합니다. 이것은 현재 수업에 대한 오래된 과제였습니다. 교수는 특별히 이것을 요구하고 그가 다시 물을 것이라고 압니다. – GuyPesto

+0

@GuyPesto : 선생님이 포인터를 사용하라고 말했고 복사 생성자, 할당 연산자 및 소멸자에 대해 가르쳐주지 않은 것 같습니다. 또는 심지어 새롭고 삭제합니까? –

+0

할당은 특히 복사 생성자, 소멸자 및 할당 연산자 생성을 요구하지 않았습니다. 내가 그들을 포함했다면 나는 아마 30 %를 잃어 버렸을 것이다. – GuyPesto

3

포인터를 아무 것도 초기화하지 않고 사용하고 있습니다. 빠른보기에서는 회원 변수 중 포인터가 포인터가 아니며 생성자 인수 중 하나도 참조가 아니어야한다는 것을 알게됩니다. 다른 곳에서는 int를 int *에 할당합니다. 컴파일러가 경고를 주었습니까?

이상한 두 가지 이유 : 정수 리터럴에 4 자리 숫자 0000을 사용하는 이유는 무엇이며, 이유는 system("pause")입니까?

+0

시스템이 일시 중지되므로 출력 된 코드를 볼 수 있습니다. 나는 이것을 할 수있는 다른 방법을 모르지만, Visual Studio 및 C++ 경험은 총 약 6 주입니다. 컴파일러 경고가없고 멤버 변수를 포인터로 사용해야했습니다. – GuyPesto

+0

@GuyPesto :이 포인터를 잘못 사용하고 있으며 문제의 원인입니다. 교수가 요청하면 교수님이 올바르게 사용하도록 도와 줘야했고,이 코드에 나쁜 점수를 주었어 야합니다. 나는 가혹한 것을 의미하지는 않지만 코드를 작동 시키려면 해당 포인터를 제거해야합니다. 여기에는 가치가 없기 때문에 코드가 작동하지 않습니다. –

+0

Ned 나는 배운 것을 의미합니다. 내가 포인터를 잘못 사용하고 있다는 것이 확실하다고 생각했기 때문에 이것이 내 질문에 대한 이유입니다. 그리고 네, 나는 10 점 만점에 7 점을 받았습니다. – GuyPesto

2

클래스의 데이터 멤버를 포인터로 저장하지 마십시오. 당신의 사용법을 줄 필요가 없습니다.

void changeGasMileage(double newGasMileage){gasMileage=&newGasMileage;}

스택에 할당 된 값을 가리 키도록 gasMileage을 설정하는 것입니다 이것이하고있다 : 한 눈에, 나는 여기에 문제를 참조하십시오. changeGasMileage이 반환되면 더 이상 해당 메모리 위치에 무엇이 있는지 알 수 없습니다. gasMileage을 포인터가 아닌 값으로 만들 수 있습니다. 그렇지 않으면, 당신은 할 필요가 :

void changeGasMileage(double newGasMileage){gasMileage= new double(newGasMileage);}

+0

죄송합니다. 명확하지 않았습니다. 수업에 대한 오래된 과제였습니다. 데이터 멤버를 포인터로 사용해야했습니다. 수업을 끝내기 전까지 모든 과제에 대해이 질문을하기 때문에 적절한 방법을 이해해야합니다. – GuyPesto

0

다른 사람은이 시나리오에서 부적절한 포인터 사용을 다루고 있습니다. 나는 동의한다.

또한 생성자가 값으로 복사를 받으면 (호출) 스택에있는 주소를 취하는 값입니다. 해당 생성자가 종료되면 로컬 변수가 파괴되고 (일반적으로 기본 유형 인 int, char, float 등), 포인터를 통해 액세스하는 것은 "정의되지 않은 동작"입니다.

이유 : 정의되지 않은 동작은 어떤 일이 일어날 수 있음을 의미합니다. 좋아, 컴파일러 진단, 또는 크래시, 또는 더 나쁜 아직 손상된 데이터로 볼 수 있지만 최악의 경우 우연의 일치는 나중에 시간이 될 때까지 작동합니다 - Programming by coincidence도 참조하십시오.

이 영역은 일단 생성자가 종료되면 다른 함수를 호출 할 때 다시 사용할 수 있도록 개방됩니다. 즉, 다른 함수를 호출하기위한 로컬 변수, 매개 변수 및 매개 변수/반환 주소를 저장할 장소가 필요합니다.

gcc (해당 버전, 해당 컴파일러 플래그)는 값을 인쇄하기 위해 스택의 해당 위치를 덮어 쓰지 않으므로 읽는 값이 예상 한 값입니다.

관련 문제