2014-11-26 2 views
0

이 질문은 이미 알고 있지만 아직 찾지 못했던 대답은 없습니다. 나는 기본 클래스에 대한 포인터 벡터를 만들고 모든 종류의 파생 클래스를 그 클래스에 추가하고있다. 이제 기본 클래스에는 파생 클래스 모두에서 재정의되고 각 클래스에 고유 한 가상 함수가 있습니다. 따라서 벡터를 통해 해당 객체를 검색하고 해당 객체에서 함수를 호출하면 올바른 객체를 호출해야합니다.하지만 기본 클래스 버전 만 호출하면됩니다. 나는 심지어 벡터에서 그들을 검색 할 때 개별 클래스를 원래 클래스로 캐스팅하려고 시도하지만 캐스팅을 거부합니다! 예 :벡터에서 벡터로 된 오브젝트 캐스팅

vector<base*> myBase; 

DerivedClass *myDerived = static_cast<DerivedClass> myBase[i]; 

내가 읽은 모든 내용에 반드시 나와야 함에도 불구하고 작동하지 않습니다. 내 디버거는이 모든 것에도 불구하고 myDerived는 여전히 유형 기반이며 내 가상 함수 버전이 호출되고 있다고합니다.

아이디어가 있으십니까? 계정을 확인

class BankAccount { 
public: 
BankAccount(string namein, string typein){ 
    name = namein; 
    type = typein; 
    balance = 0; 
} 
virtual string getType(); 
virtual void printTransactions() = 0; 
virtual int withdraw(double amt){ 
    return getBalance() -amt; 
} 
}; 

class SavingsAccount: public BankAccount { 
public: 
SavingsAccount(string namein, string typein); 
void addTransaction(string transType, string name); 
virtual int withdraw(double amt); 
void printTransactions(); 
virtual string getType(); 

private: 

}; 

SavingsAccount::SavingsAccount(string namein, string typein): BankAccount(namein, typein) { 

} 

int SavingsAccount::withdraw(double amt){ 
double aBal = getBalance() - amt; 
if (aBal > 0){ 
setBalance(aBal); 
} 
return getBalance() - amt; 

} 


class CheckingAccount: public SavingsAccount { 
public: 
CheckingAccount(string nameIn, string typein): SavingsAccount(nameIn, typein){ 

} 
virtual int withdraw(double amt); 
void printTransactions(); 
string getType(){ 
    return "Checking"; 
} 

}; 

int CheckingAccount::withdraw(double amtIn){ 
double newBal = getBalance() - amtIn; 
if (newBal < 500.00 && newBal > 2.49) { 
    setBalance(newBal - 2.50); 
} 
return newBal; 

}

int main(int argc, const char * argv[]) 
{ 
vector<BankAccount*> myAccts; 
SavingsAccount *mySav; 
CD *myCD; 
CheckingAccount *myCheck; 

switch (option) { 
     case 1: { 
      string name; 
      string type; 
      cout << "Enter name: "; 
      cin >> name; 
      getline(cin, dump); 
      cout << "Enter account type: "; 
      cin >> type; 
      getline(cin, dump); 
      if (type.compare("Checking") == 0) { 
       CheckingAccount myCheck1 = CheckingAccount(name, type); 
       myAccts.push_back(&myCheck1); 

      } 
     case 3:{ 
     for (int x = 0; x < myAccts.size(); x++) { 
       if (myAccts[x]->getName() == name && myAccts[x]->getType() == type) { 
        if (type == "Savings") { 
         mySav = static_cast<SavingsAccount*>(myAccts[x]); 
         double y = mySav->withdraw(amt); 
         if (y < 0){ 
          cout << "Insufficient funds!"; 
          } 
        } 
        if (type == "Checking") { 
         myCheck = myAccts[x]->GetDerived(); 
         double y = myCheck->withdraw(amt); 
         if (y < 0){ 
          cout << "Insufficient funds!"; 
          } 
         if (y < 497.5) { 
          cout << "Withdrawal fee: $ 2.50" << endl; 
         } 


        } 

} 

은 저축 예금의 자식입니다. 죄송합니다.

+1

DerivedClass * myDerived = static_cast myBase [i]; – radar

+1

'dynamic_cast'를 사용하십시오 - static_cast보다 우수합니다. –

+0

동적 캐스트는 Null을 반환합니다. – user3712524

답변

4

개념이 정확하며 전송이 필요하지 않습니다. 가상 함수의 전체적인 포인트는 기본 클래스 포인터 또는 참조를 보유하고 가상 함수를 호출하는 경우이 함수의 가장 파생 된 버전이 런타임에 호출된다는 것입니다.

내가 볼 수있는 오류는 이것이다 :

if (type.compare("Checking") == 0) { 
     CheckingAccount myCheck1 = CheckingAccount(name, type); 
     myAccts.push_back(&myCheck1); 

당신은 다음 주소의 복용과 벡터에 그 주소를 밀어 스택에 당좌 계정을 만들 수 있습니다. if 블록 끝에서 myCheck1은 범위를 벗어나 파괴됩니다. 벡터에는 스택의 위치에 대한 주소가 있으며 정의되지 않은 동작을가집니다.

대신 수행

if (type.compare("Checking") == 0) { 
     myAccts.push_back(new CheckingAccount(name, type)); 

그리고 다른 종류의 비슷한

을. 그 모든 던지기를 제거하십시오. 이 버전에서는 마지막에 벡터의 모든 항목을 삭제해야합니다. std::vector<std::unique_ptr<BankAccount>>을 사용하는 경우 unique_ptr은 할당 된 객체를 정리합니다.

0

시도해 보셨습니까?

class base 
{ 
public: 

inline DerivedClass *GetDerived() {return (DerivedClass*)this;} 

... 
}; 

DerivedClass *myDerived = myBase[i]->GetDerived(); 
+1

다운 캐스팅 할 때'dynamic_cast'를 사용해야합니다. 왜냐하면 여러분이 감추고있는 객체가 파생 된 타입인지를 검사 할 수 있기 때문입니다. 그렇지 않으면 캐스트 결과가 너무 많은 의미를 가지지 않으며 많은 두통을 유발할 수 있습니다. – vsoftco

3

당신은 당신의 계정을 만들 new를 사용할 필요가 ... 당신은 : if 범위 있음을 떠날 때

if (...) 
{ 
    CheckingAccount myCheck1 = CheckingAccount(name, type); 
    myAccts.push_back(&myCheck1); 
} 

이 ... myCheck1가 파괴됩니다의 상에 효과적으로 임의 위치에 대한 포인터로 myAccts를 떠나 스택에 액세스 할 경우 정의되지 않은 동작이 있습니다.

if (type == "Checking") 
    myAccts.push_back(new CheckingAccount(name, type)); 

당신은 다음 vector 요소 delete의 일치가 필요합니다 :로 변경합니다. 인터넷 검색 "C++ 새로운 자습서"좋은 생각이 될 것입니다.다음 단계는 스마트 포인터를 사용하는 방법을 배우는 것입니다 (예 : std::shared_pointer). 이는 기억의 부담을 delete으로 제거합니다. 당신이 호출의 유형 특정 작업을 수행 할 필요없이 가상 함수 올바른 버전이 있는지라고하게 - double y = myAccts[x]->withdraw(amt);은 특히

  for (int x = 0; x < myAccts.size(); x++) 
      if (myAccts[x]->getName() == name && myAccts[x]->getType() == type) { 
       double y = myAccts[x]->withdraw(amt); 
       if (y < 0) 
        cout << "Insufficient funds!"; 
       if (type == "Checking" && y < 497.5) 
         cout << "Withdrawal fee: $ 2.50" << endl; 
      } 

주의 사항 :

는 "사례 3"/ 수정을 단순화 할 수있다 암호.

관련 문제