2014-09-09 3 views
0

저는 클래스와 벡터로 연습하고 벡터에 개체를 저장하고 있습니다. 기본 클래스 객체와 그 객체를 상속 한 클래스 객체를 저장 한 후 내 컴파일러는 상속 된 클래스 객체가 존재하지 않는다는 오류를 반환합니다.벡터에 개체를 저장하면 컴파일러에서 요소가 존재하지 않는다고 말합니다.

자동차 클래스와 스포츠카 클래스, 벡터 자동차의 객체 저장

class Car 
{ 
    public: 
     Car(); 
     void stop(); 
     int get_speed() const; 
     void new_speed(int fspeed); 

    protected: 
     int speed; 
}; 

class Sportscar : public Car 
{ 
    public: 
     Sportscar(); 
     void turbo(); 

    private: 
     bool hasTurbo; 
}; 

자동차에서 상속 :

vector<Car*> cars(2); 

    cars[0] = new Car(); 
    cars[1] = new Sportscar(); 
을 여기에 내가 중요한 비트 있다고 가정 무엇인가

cars[0]cars[1]에 액세스하는 경우, cars[0]이 양호하게 액세스되지만, cars[1]가되지 않습니다 :

#include <iostream> 
#include <cstdlib> 
#include <vector> 
using namespace std; 

class Car 
{ 
    public: 
     Car(); 
     void stop(); 
     int get_speed() const; 
     void new_speed(int fspeed); 

    protected: 
     int speed; 
}; 

class Sportscar : public Car 
{ 
    public: 
     Sportscar(); 
     void turbo(); 

    private: 
     bool hasTurbo; 
}; 

// Constructor for class Car 
Car::Car() 
{ 
    speed = 1; 
} 

// Function to stop the car 
void Car::stop() 
{ 
    speed = 0; 

    cout << "You stop the car.\n" << endl; 
} 

// Function to get current speed of the car 
int Car::get_speed() const 
{ 
    return speed; 
} 

// Function to "accelerate" the car 
void Car::new_speed(int fspeed) 
{ 
    int newspeed; 

    cout << "Speed up by how many mp/h? "; 
    cin >> newspeed; 

    speed = (fspeed + newspeed); 

    cout << "You speed up.\n" << endl; 
} 

// Sportscar constructor to set hasTurbo to 0 (no) 
Sportscar::Sportscar() 
    // Not sure if this is necessary 
    : Car() 
{ 
    hasTurbo = 0; 
} 

// Function to designate if the car has turbo 
void Sportscar::turbo() 
{ 
    hasTurbo = 1; 

    cout << "You have activated turbo and have greater acceleration.\n" << endl; 
} 

int main(void) 
{ 
    vector<Car*> cars(2); 

    cars[0] = new Car(); 
    cars[1] = new Sportscar(); 

    //Car drive; 
    //Sportscar drivefast; 
    char ans; 
    char sport; 

    // Asks user for input A, B, C, or Q until user chooses Q to quit 
    while(1) 
    { 
     cout << "Enter 'A' for current speed, 'B' to speed up, or 'C' to stop. 'Q' to quit." << endl; 
     cin >> ans; 

     // If users chooses A, calls get_speed() function and outputs current speed 
     if (ans == 'A') 
     { 
      cout << "Your current speed is " << cars[0]->get_speed() << " mp/h.\n" << endl; 
     } 

     // If user chooses B, calls new_speed() function to increase speed according to 
     // user's specifications 
     else if (ans == 'B') 
     { 
      // Asks user if they have turbo Y/N 
      cout << "Do you want to use turbo? Y/N: "; 
      cin >> sport; 

      // If user does have turbo, hasTurbo is set to 1 (yes) and function 
      // new_speed() is called 
      if (sport == 'Y') 
      { 
       cars[1]->turbo(); 
       cars[0]->new_speed(cars[0]->get_speed()); 
      } 

      // If user does not have turbo, hasTurbo stays at 0 (no) and function 
      // new_speed() is called 
      else if (sport == 'N') 
      { 
       cars[0]->new_speed(cars[0]->get_speed()); 
      } 

      // If user answers other can Y or N, tells user input is incorrect 
      else 
      { 
       cout << "Incorrect input.\n" << endl; 
      } 
     } 

     // If user chooses C, calls stop() function and reduces car's speed to 0 
     else if (ans == 'C') 
     { 
      cars[0]->stop(); 
     } 

     // If user chooses Q, program ends 
     else if (ans == 'Q') 
     { 
      exit(0); 
     } 

     // If user chooses other than A, B, C, or Q, tells user input is incorrect 
     else 
     { 
      cout << "Incorrect input.\n" << endl; 
     } 
    } 
} 

: 여기

cars[1]->turbo(); 
cars[0]->new_speed(cars[0]->get_speed()); 

조금 모든 나는이 작은 자동차 게임 거라고 내가 처음에 확실하지 않았다 때문에 여기 저기입니다 전체 코드입니다 마지막으로, 여기 내 컴파일러 오류입니다 :

enter image description here

나는주의해야 그 나는,695에 액세스하는 라인을 제거하는 경우, 프로그램을 컴파일하고 잘 실행됩니다.

답변

2

벡터는 Car* 유형의 벡터로 선언되었습니다. Car 유형의 개체에는 turbo 멤버 함수가 없습니다. 당신은 Sportscar* 유형에 포인터를 캐스팅해야합니다

static_cast<Sportscar*>(cars[1])->turbo(); 
+1

'cars [1]'이 실제로 'Sportscar'가 아니었던 경우 이는 정의되지 않은 동작을 유발합니다. 또한 UB가 static_cast를 반복하지 않고도 cars [1]을 (를) 삭제하게됩니다. 'Car' 다형성을 만드는 것이 아마 행동의 가장 좋은 원인 일 것입니다. –

0

carsvector<Car*>이며, Car 참으로 turbo() 멤버 함수를 가지고 있지 않습니다.

C++은 정적 이름 조회를 사용합니다. Car*을 보면 실행시에 Sportscar을 가리킨 다음 turboSportscar으로 봅니다.

if (auto sc = dynamic_cast<Sportscar*>(cars[1])) { 
    sc->turbo(); 
} else { 
    std::cout << "cars[1] is not a Sportscar\n"; 
} 

(그건 당신이 알고 있기 때문에 당연히 스포츠카 당신이 무조건 수 : 당신이 그 동적 거동을 원하는 경우 (실제로는 다형성을 지원하도록 기본 클래스를 수정 후) 스스로를 작성할 수있어

당신이 얻을 수있는 static_cast 그것뿐만 아니라)


동적 동작은 가상 방법입니다 : 기본 클래스는 가상의 방법을 통해 일부 '인터페이스'를 선언하고 해당 기본 유형의 클래스를 그 가상의 방법을 사용할 수 있습니다. 런타임에 클래스가 실제로 파생 된 유형이면 파생 된 메소드가 호출됩니다.bfoo를 호출

struct Base { 
    virtual void foo() { std::cout << "Base\n"; } 
    virtual ~Base() {} 
}; 

struct Derived : Base { 
    virtual void foo() override { std::cout << "Derived\n"; } 
}; 

int main() { 
    Base *b = new Derived; 
    b->foo(); // prints "Derived" 
} 

에만 있기 때문에, 컴파일시에 컴파일러는 Base이 방법 foo을 가지고 있음을 알 수 허용되지만이 방법은 가상이기 때문에 컴파일러는 수 있도록 기계를 설정의 실제 메소드 구현 런타임에 호출되는 객체의 실제 유형에 따라 런타임에 결정됩니다. 그러나이를 설정하기 위해 컴파일러는 에 대해 아무 것도 모른 채 가상 함수 인 foo을 알아야합니다.

+1

'dynamic_cast'는 다형성 클래스에서만 작동합니다; 'Car'는 그 캐스트가 작동하는 가상 함수 (소멸자가 선호 됨)가 필요합니다. –

+0

@MattMcNabb 네, 맞습니다. 나는 그것이 이미 아니라고 알아 차리지 못했다. – bames53

0

SportsCar 클래스가 Car에서 상속 받으면 메서드를 잘 추가 할 수 있습니다. 벡터에 SportsCar를 저장하면 모든 SportsCar 데이터가 유지되지만 자동차 전용으로 간주되기 때문에 액세스 할 수 없습니다. "turbo()"메서드에 액세스하려면 "cars [1]"객체를 SportsCar로 캐스팅해야합니다. 만약 당신이 당신의 벡터에 반대하지 명심해야

SportsCar mySportsCar = (SportsCar)cars[1]; 
//Now you can call .turbo() on mySportsCar 

//You could also do it in one line, like so : 
((SportsCar)cars[1]).turbo(); 

것은 스포츠카이며, 그 때문에 당신이 그들을 캐스팅하기 전에 유형을 확인해야하거나, 예외가 던져지는 것입니다. 다음과 같은 여러 가지 방법이 있습니다 :

if(SportsCar *mySportsCar = dynamic_cast<SportsCar*>(&cars[0])) 
{ 
    //Your car was successfully casted, you can use it here 
} 
else 
{ 
    //Your car is not a SportsCar 
} 
+0

C 스타일의 캐스트를 사용하기 위해 downvoted; C++ 캐스트를 사용하도록 다시 작성하면 업데이트됩니다. (C++에서는 C 스타일의 캐스트가 필요하지만 실제로는 그렇지 않습니다.) 또한'dynamic_cast'는베이스에 가상 함수가있는 경우에만 작동합니다. –

관련 문제