문제

런타임에 클래스에 필드를 추가하는 방법이 있습니까 (이전에 존재하지 않은 필드)? 이 스 니펫과 같은 것 :

Myobject *ob; // create an object
ob->addField("newField",44); // we add the field to the class and we assign an initial value to it
printf("%d",ob->newField); // now we can access that field

나는 그것이 어떻게 될지 상관하지 않습니다. 나는 그것이 추악한 해킹인지 아닌지 신경 쓰지 않습니다. 가능하다면 작은 예를 알고 싶습니다.

또 다른 예: 이 클래스를 설명하는 XML 파일이 있다고 가정합니다.

<class name="MyClass">
   <member name="field1" />
   <member name="field2" />
</class>

그리고 클래스에 "필드"필드 1과 "Field2"를 "추가하고 싶다 (클래스가 이미 존재한다고 가정). 이것이 클래스 코드라고 가정 해 봅시다 :

class MyClass {
};

런타임에 클래스를 만들고 싶지 않고 기존의 멤버/필드를 추가하고 싶습니다.

고맙습니다 !

도움이 되었습니까?

해결책

지도와 변형을 사용하십시오.

예를 들어, boost :: variant를 사용합니다. 보다 http://www.boost.org/doc/libs/1_36_0/doc/html/variant.html

(물론 XML 속성의 유형에 맞게 직접 만들 수 있습니다.)

#include <map>
#include <boost/variant.hpp>

typedef boost::variant< int, std::string > MyValue ;
typedef std::map<std::string, MyValue> MyValueMap ;

MyValuemap을 수업의 구성원으로 추가하면 이름에 따라 속성을 추가 할 수 있습니다. 이는 코드를 의미합니다.

oMyValueMap.insert(std::make_pair("newField", 44)) ;
oMyValueMap.insert(std::make_pair("newField2", "Hello World")) ;
std::cout << oMyValueMap["newField"] ;
std::cout << oMyValueMap["newField2"] ;

MyObject 클래스에서 캡슐화 하고이 MyObject 클래스에서 오른쪽 과부하 된 액세서를 추가함으로써 위의 코드는 다소 명확 해집니다.

oMyObject.addField("newField", 44) ;
oMyObject.addField("newField2", "Hello World") ;
std::cout << oMyObject["newField"] ;
std::cout << oMyObject["newField2"] ;

그러나 C ++의 유형 안전을 어느 정도 잃게됩니다. 그러나 XML의 경우 이것은 피할 수없는 것 같습니다.

다른 팁

컴파일러가 컴파일 시간에 참조를 해결해야하므로 오류가 발생하기 때문에 설명하는 방식으로 설명 할 수있는 방법이 없습니다.

하지만 참조하십시오 보편적 인 디자인 패턴.

컴파일 시간에 정적 점검으로 인해 구문을 만들 수는 없지만 구문을 기꺼이 수정하려면 동일한 효과를 쉽게 달성 할 수 있습니다. 문자열-> blob 매핑이있는 사전 멤버를 갖는 것은 매우 쉽고 다음과 같은 멤버 기능이 있습니다.

template< typename T > T get_member( string name );
template< typename T > void set_member( string name, T value );

원하는 경우 구문을보다 작고 까다 롭게 만들 수 있습니다 (예 : '->'연산자 오버라이드 사용). 또한 활용할 수있는 컴파일러 별 트릭도 있습니다 (예를 들어 MSVC는 __declSpec (Property)를 지원하므로 특정 형식의 메소드에 참조 변수에 참조를 매핑 할 수 있습니다). 그러나 하루가 끝나면 컴파일러가 언어로 받아들이지 않는 일을 할 수 없을 것입니다.

짧은 버전 : 할 수 없습니다. 이에 대한 기본 지원이 없으며 C ++는 정적으로 입력하고 컴파일러 조작 할 각 물체의 구조를 알아야합니다.

추천: 임베디드 간호사를 사용하십시오. 그리고 자신의 글을 쓰지 말고 (아래 참조) 이미 작동하고 디버깅 된 것을 얻으십시오.


할 수있는 일 : 귀하의 요구에 대해 충분한 간호사를 구현하십시오.

같은 데이터 멤버로 클래스를 설정하는 것은 간단합니다.

std::vector<void*> extra_data;

런타임에 임의의 데이터를 첨부 할 수 있습니다. 이것의 비용은 다음과 같은 방법으로 해당 데이터를 직접 관리해야한다는 것입니다.

size_t add_data_link(void *p); // points to existing data, returns index
size_t add_data_copy(void *p, size_t s) // copies data (dispose at
                                        // destruction time!), returns 
                                        // index 
void* get_data(size_t i); //...

그러나 그것은 한계가 아닙니다. 조금 더주의를 기울이면 임의의 데이터를 이름과 연관시킬 수 있으며 원하는 만큼이 체계를 자세히 설명 할 수 있습니다 (유형 정보 추가 등). Down To는 런타임 유연성을 관리하기 위해 간호사를 구현하고 있습니다.

아니오 -C ++는 이와 같은 유형 시스템의 조작을 지원하지 않습니다. 어느 정도의 런타임 반사 (예 : .NET)가있는 언어 조차도이 패러다임을 정확하게지지하지 않습니다. 할 수있는 훨씬 더 역동적 인 언어가 필요합니다.

나는 이것을보고 있었고 나는 약간의 검색을했다.이 코드 스 니펫은 다음에서 얻었다. 마이클 해머의 블로그사용 하여이 작업을 수행하는 좋은 방법 인 것 같습니다. 부스트 :: 누구

먼저 키 (예 : 변수 이름)와 값을 포함하는 std :: 맵을 정의하는 구조를 정의합니다. 함수는 쌍에 광고를하고 값을 얻기 위해 함수와 함께 설정하도록 정의됩니다. 당신이 나에게 물어 보면 아주 간단하지만, 더 복잡한 일을하기 전에 시작하는 좋은 방법 인 것 같습니다.

struct AnyMap {
  void addAnyPair( const std::string& key , boost::any& value );

  template<typename T>
  T& get( const std::string key ) {
    return( boost::any_cast<T&>(map_[key]) );
  }

  std::map<const std::string, boost::any> map_;
};

void AnyMap::addAnyPair( const std::string& key , boost::any& value ) {
  map_.insert( std::make_pair( key, value ) );
}

결론적으로, 이것은 C ++가 엄격한 유형을 확인하는 언어이기 때문에 해킹입니다. 따라서 몬스터는 규칙을 구부리는 사람들에게 있습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top