2014-12-07 4 views
0

이 코드를 좀 더 읽기 쉽도록 만드는 코드를 잘라내는 것은 이해하기 어렵습니다.파생 클래스 멤버 변수에 액세스하는 기본 클래스 포인터?

class player : public character{ 
public: 
    // ---------stuff------- 

protected: 
    // ------stuff-------- 
    vector <item*> inventory; 
}; 

class item { 
public: 
    // -----stuff------------ 

    virtual float getHealth(){}; 
    virtual int getDef(){return 0;}; 
    virtual int getAttAcc(){return 0;}; 
    virtual int getAttPow(){return 0;}; 
    virtual ~item(); 
protected: 
    string name; 
    string type; 
    int value; 
    int weight; 

}; 

class weapon : public item{ 
public: 
    weapon(int attPow, int attAcc, int inValue, int inWeight, string inType, string inName); 
    weapon(const weapon& cWeapon); 
    int getAttAcc(weapon& weapon){return attAcc;}; 
    int getAttPow(){return attPow;}; 
    ~weapon(){}; 
protected: 
    int attAcc; 
    int attPow; 
}; 

내 생각에는 attAcc 및 attPow에 액세스하기 위해 무기 (포인터가 인벤토리에 저장되어 있어야 함)가 필요할 때가 생깁니다.
내가 시도한 것 : 가상 함수를 추가하고 파생 클래스로 변경하려고했습니다.

나는 기본 클래스에서 벗어나려고했지만 인벤토리는 항목에 대한 포인터 벡터이므로 허용하지 않습니다.

원래 무기와 방어구에 2 개의 포인터가 있어야하지만 인벤토리가 작동하지 않는 항목 포인터이기 때문에.

다른 항목에 대한 수업을 빠져 나오기 때문에, 다른 항목에 대한 수업을 빠져 나왔습니다. 3 파생 된 클래스가 있기 때문에 기본 클래스에 대한 포인터가 될 인벤토리가 필요합니까?

+0

이 https://stackoverflow.com/questions/11855018/c-inheritance-downcasting를 참조하십시오 당신은 때 알아야하고있는 당신이 어떻게 든 캐스트 할 필요가 객체. – Robert

+0

나는 주조를보고 있었고 나는이 경우 어떻게 작동 할 것인가를 너무 확신하지 못했습니다. 내 인벤토리의 항목을 가리 키기 위해 캐스트 포인터를 사용할 수 있습니까? 인벤토리 [1]이 무기 인 경우 액세스 권한을 얻기 위해 사례 값을 사용할 수 있습니까? –

+0

예.하지만 캐스팅 할 때 무기인지 확인해야합니다. – Robert

답변

2

확실하지 않은 부분이 무엇입니까?

가상 함수를 사용하려면 파생 클래스에서 virtual 키워드를 사용하는 것이 좋습니다.

그러나 가상 함수에는 동일한 매개 변수 (서명)가 있어야하며, 그렇지 않으면 기본 클래스 함수에 과부하가 걸리고 가상 함수 메커 니크가 작동하지 않습니다.

예를 들어, int weapon :: getAttAcc (weapon & weapon) 함수는 기본 함수 int get :: getAttAcc()를 재정의하지 않습니다. 초기 함수에는 매개 변수가 없기 때문입니다.

int item :: getAttAcc (무기 & 무기)에 매개 변수를 추가 할 수 있습니다 (원하는 경우). 동료 해설자에 의해 제안,

class Item { 
    public: 
    virtual int getItemType() = 0; // this will make function pure virtual 
}; 

class Weapon : public Item { 
    public: 
    virtual int getItemType() { return 1; } 
    int getAttAcc() {return attAcc;} 
} 

Item * item = // something 
if (item.getItemType() == 1) // weapon 
{ 
    Weapon * weapon = (Weapon)item; 
    weapon->getAttAcc(); 
} 

또는 :

또 다른 해결책은 유형 기능을 추가 할 수 있습니다. 더 C++ 방법 :

// cast will be successful only for Weapon type object. 
if (Weapon * weapon = dynamic_cast<Weapon *>(item)) { // weapon 
    weapon->getAttAcc(); 
} 
+1

'if (Weapon * weapon_ptr = dynami_cast (item)) {weapon_ptr-> getAttAcc();를 사용하십시오. }'. 'getItemType' 함수를 수동으로 추가하는 것보다 안전하고 타이핑하기가 쉽지 않습니다. 귀하의 다른 지점은 정확합니다. – 5gon12eder

+0

C++에서 C 스타일 캐스트를 사용하면 다형성 유형을 다룰 때 위험한 상황이 발생합니다. \ 대신 C++ 주조 연산자를 사용하십시오. 이 경우에는'dynamic_cast'가 적절한 메소드입니다. –

+0

"그러나 가상 함수는 동일한 매개 변수를 가져야하며 가상으로 계산되지 않는 다른 방법"이 필요합니다. "그러나 가상 함수는 동일한 서명이있는 함수로만 재정의 할 수 있습니다. 그렇지 않으면, 그냥 * 과부하 *. " – 5gon12eder

0

가장 즉각적인 오류는 INT 무기 :: getAttAcc 서명 가상 함수 INT 항목과 일치하지 않습니다 (무기 &) :: getAttAcc()를 선언 한 것입니다. 일치하지 않으므로 기본 클래스의 함수를 재정의하지 않았습니다.

더 근본적으로는 클래스 무기의 의미있는 항목 만있는 함수를 선언 할 클래스 항목에 대한 이해가되지 않습니다. (물론, 의미있는 것이 아니라면, 갑옷의 아이템도 attPow와 attAcc를 가지고 있습니까?)

즉, getAttAcc를 만들지 마십시오 ("공격 성공 확률"의 약자로 가정) 클래스 항목의 가상 함수 모든 항목을 공격에 사용할 수있는 경우가 아니면

대신 인벤토리를 조사하는 동안 무기 만 수행하려는 것이 있으면 dynamic_cast를 사용하여 유형을 확인하십시오.예를 들어 :

class weapon : public item { 
public: 
    int getAttAcc() { return attAcc; }; 
    ... 
} 


item *anItem = ...; 

if (weapon* aWeapon = dynamic_cast<weapon*> (anItem)) { 
    ... do something with aWeapon->getAttAcc() ... 
    ... and/or with aWeapon->getAttPow() ... 
    } 
관련 문제