2012-12-31 2 views
0

배열이나 벡터에 다양한 데이터 유형을 저장하려고합니다. 지금까지 저는 벡터에 각 객체에 대한 포인터로 저장 될 기본 클래스를 사용하여 데이터를 가져온 다음 캐스팅하여 데이터를 다시 가져옵니다. 이것은 int에서 잘 작동하지만 다른 유형의 데이터에서는 액세스 위반 예외가 발생합니다. 내 설명이없는 아주 좋은 경우벡터에 다양한 유형 저장

죄송합니다, 여기에 내가 도움이되기를 바랍니다 의견 내 코드는 다음과 같습니다

:

의미의 일부 유사하게
//Base class 
class MenuProperty 
{ 
private: 
    std::string Name; 

public: 
    MenuProperty(std::string Name) : Name(Name) {}; 
    ~MenuProperty() {}; 

    std::string GetName(); 

}; 

//Typed class used to store data 
template<class T> 
class TMenuProperty : public MenuProperty 
{ 
private: 
    T Data; 

public: 
    TMenuProperty(std::string Name, T Data) : MenuProperty(Name), Data(Data) {}; 

    T GetData() 
    { 
     return this->Data; 
    } 
}; 

//Class with no type and data pointer to retrieve data 
class cpMenuProperty : public MenuProperty 
{ 
private: 
    VOID* Data; 

public: 
    cpMenuProperty(std::string Name) : MenuProperty(Name) {}; 

    VOID* GetPointer() 
    { 
     return this->Data; 
    } 
}; 

희망, 여기 내 테스트 코드

int main() 
{ 
    TMenuProperty<double> fP("Test2", 33.7354); //Create instance of property 

    MenuProperty* fMP = &fP;     //Make a pointer to the object 

    cpMenuProperty* Test;      //Make a pointer to the retrieving 
               //object 

    std::vector<MenuProperty*>    Vec; 
    std::vector<MenuProperty*>::iterator it; 

    Vec.push_back(fMP);       

    it = Vec.begin(); 

    Test = static_cast<cpMenuProperty*>(*it); //Cast the first object in the list 
               //list to the same type as the 
               //retrieveing object 


    double Data = *(double*)Test->GetPointer(); //Dereference and access, this is 
               //where the exception is thrown 

    std::cout << Data; 



    int Ret; 
    std::cin >> Ret; 
} 

나는 여기에 기념비적 인 오류가있을 수 있지만 지금까지 읽어 보는 시간을 내 주셔서 감사합니다. 어떤 도움도 감사하고 건설적인 비판도 있습니다!

+0

TMenuProperty fP ("Test2", 33.7354); TMenuProperty로 변경하십시오. * fP = new TMenuProperty fP ("Test2", 33.7354); –

+0

참조 http://stackoverflow.com/questions/7804955/heterogeneous-containers-in-c – learnvst

답변

2

스택에 TMenuProperty 개체를 초기화하면 cpMenuProperty로 캐스팅됩니다. cpMenuProperty의 void * 데이터에 할당 된 메모리는 절대로 없습니다. TMenuProperty와 cpMenuProperty는 같은 클래스에서 파생된다는 점을 제외하고는 관계가 없습니다. 이 디자인은 절대로 작동하지 않습니다.

  • void *를 모두 제거하십시오. 그것은 문제를 요구하고 있습니다.
  • 당신이하고있는 것을 100 % 알지 못하면 static_cast <>을 사용하지 마십시오. dynamic_cast를 사용하면 전환이 유효하지 않다고 말했을 것입니다. (이 코드를 시도한 것 같지만 코드를 강제로 컴파일하려면 static_cast로 되돌아갑니다 :))
  • 왜 사용하지 않습니까? TMenuProperty 끝까지? 그 접근 방식이 효과가있다.
  • 다른 방법은 boost :: variant와 boost :: any를보세요.
  • 만약 당신이 용감하다는 것을 알고 있고 당신이하고있는 것을 정말로 알고 있다면 (불쾌감은 없지만, 당신이 이것을받을 자격이 있다고 생각하지는 않습니다.) 랩 할 데이터 유형이 메모리 레이아웃면에서 충분히 균일하다면, 적절한 메모리 패딩 설정으로 코드를 작동시키고 메모리 정렬을 특정 방식으로 강제 설정할 수 있습니다. 그러나 나는 아무렇지도 않게 시나리오를 가져올 수 없습니다. 그렇게 할 이유가 무엇인지 찾아야합니다. 그래서이 글에서 알 수 있듯이 cpMenuProperty를 삭제하고 추상 기본 클래스/템플릿 기반 클래스 접근 방식 만 사용하도록 권장 할 수 있습니다.
+0

글쎄, 이론은 타입 캐스트를 강제로 void * 포인터가 데이터의 시작 부분에 떨어지는 것을 허용한다는 것입니다 TMenuProperty. 이 접근 방식의 단점을 설명해 주셔서 감사합니다. 나는이 것을 다시 생각할 것이다 – Andre

+0

어, 생각해 보면 cpMenuProperty로 접근법을 사용할 필요조차 없다. 시간을 낭비해서 죄송합니다. 게시하기 전에 더 많은 생각을 했어야합니다. – Andre

0
#include<iostream> 
#include<vector> 
#include<iterator> 
#include<memory> 
class base { 
public: 
virtual void foo(){ 
     std::cout << "in base" << std::endl; 
    } 
}; 

class derived : public base { 
public: 
virtual void foo(){ 
     std::cout << "in derived" << std::endl; 
    } 
}; 

int main() 
{ 
    std::vector<std::unique_ptr<base>> vec; 
    vec.emplace_back(new derived); 
    static_cast<derived*>(vec[0].get())->foo(); 
    return 0; 
    } 

모범 사례를 사용한 고전적인 예입니다.

관련 문제