2010-12-20 9 views
3

나는 C++ 템플릿 'mixins'을 사용하여 공유 기능을 추가하여 새로운 VCL 구성 요소를 만들려고합니다. 예 ...C++ 템플릿은 VCL 클래스와 잘 작동합니까?

template <class T> class Mixin : public T 
{ 
private: 
    typedef T inherited; 

// ...additional methods 

public: 
    Mixin(TComponent *owner) : inherited(owner) 
    { 
    // .. do stuff here 
    }; 
}; 

은 다음과 같이 사용합니다 :

class MyLabel : public Mixin<TLabel> 
{ 
    .... 
} 

class MyEdit : public Mixin<TEdit> 
{ 
    .... 
} 

이제 모든 것이 잘 컴파일과 믹스 인 물건이 작동하는 것 같다 - 내가 시도까지 사용하여 스트림에 구성 요소를 저장 TStream-> WriteComponent, 상속 된 속성 (예 : TLabel.Width/Height/등)이 작성되지 않습니다. 위에 표시된 것과 같이 'null'믹스 인 경우에도 마찬가지입니다.

TForm, TEdit 등에서 직접 클래스를 파생 할 때 내 코드가 잘 작동하며 클래스가 스트리밍 시스템에 올바르게 등록됩니다.

답변

8

빠르고 간단한 대답은 다음과 같습니다. 아니오; 템플릿을 처리 할 때 컴파일러는 스트리밍을 작동시키기 위해 적절한 설명자를 생성하지 않습니다. 그러나 이것은 이전에 나온 것이기 때문에, 나는 무엇이 빠졌는지 알아 내기 위해 표지 밑을 들여다 보았다. 그리고 제가 발견 한 것은 그것이 거의 다 있다는 것입니다. 그래서 여기에 조금 더 많은 정보가 있습니다.

Upfront 컴파일러는 템플릿 기반 유형을 델파이로 취급하지 않습니다. 예를 들어, 다음과 같이 수행

void testing() 
{ 
    __classid(Mixin<Stdctrls::TLabel>); // Error Here 
} 

을 ... 당신은 오류를 볼 수 있습니다

"오류 E2242 Test.cpp에 53 : __classid (즉, 클래스가 __declspec 표시 델파이 스타일 클래스 유형이 필요 (delphiclass) 또는 System :: TObject)에서 파생 된 함수 테스트() "

기본적으로 컴파일러는이 유형/클래스를 Delphi 클래스 [ie TObject에서 파생 된]. 내부적으로 유형에 델파이 호환 여부를 나타내는 기호가 있습니다. 그리고 내가 계층 구조를 따라 가야한다면 델파이 스타일로 타입을 표시하도록 컴파일러를 속일 수 있다는 것을 알았습니다. 이것은 객체의 인스턴스를 생성 할 때해야 할 일입니다. 그래서,이 오류를 해킹 멀리 간다 :

void testing() 
{ 
    typedef Mixin<Stdctrls::TLabel> __ttype; 
    std::auto_ptr<__ttype> c2(new __ttype(0)); 
    __classid(Mixin<Stdctrls::TLabel>); // No more errors here 
} 

하지만 훨씬 좋네요가 같이 템플릿에서 직접 __declspec (delphiclass)를 사용하는 사실이었다 그래서 지금

template <class T> 
class __declspec(delphiclass) Mixin : public T { 
private: 
    int i; 
    typedef T inherited; 
public: 
    __fastcall Mixin(TComponent *owner) : inherited(owner) {}; 
}; 

컴파일러 취급하는 델파이 클래스는 해킹이없는 델파이 스타일 클래스로서, 좀 더 엿보고 아마도 당신이 겪고있는 문제를 발견했습니다 : 델파이 클래스는 TTypeData.PropCount 필드 -을가집니다. 이것은 클래스 속성의 합계입니다. 그 기본 클래스.정보의 여러 가지 계산하는 방법으로, 컴파일러는 써 인해 '0'템플릿이

당신은에서와 같이 PropCount을 인쇄하여 볼 수 있습니다 :(포함되는 필드 :

#include <Stdctrls.hpp> 
#include <cstdio> 
#include <memory> 
#include <utilcls.h> 

class TCppComp : public Classes::TComponent { 
    int i; 
public: 
    __fastcall TCppComp(TComponent* owner): Classes::TComponent(owner) {}; 
__published: 
    __property int AAAA = {read=i, write=i}; 
}; 

template <class T> 
class __declspec(delphiclass) Mixin : public T { 
private: 
    int i; 
    typedef T inherited; 
public: 
    __fastcall Mixin(TComponent *owner) : inherited(owner) {}; 
}; 

typedef Mixin<TCppComp> TMixinComp; 

void showProps(TClass meta) { 
    PTypeInfo pInfo = PTypeInfo(meta->ClassInfo()); 
    int Count = GetPropList(pInfo, tkAny, NULL); 
    TAPtr<PPropInfo> List(new PPropInfo[Count]); 
    std::printf("Class: %s - Total Props:%d\n", 
        AnsiString(pInfo->Name).c_str(), Count); 
    GetPropList(pInfo, tkAny, *(reinterpret_cast<PPropList*>(&List))); 
    for (int i = 0; i < Count; i++) { 
    AnsiString propName(List[i]->Name); 
    std::printf("\t%s\n", propName.c_str()); 
    } 
} 

void test() { 
    showProps(__classid(TCppComp)); 
    showProps(__classid(TMixinComp)); 
} 

int main() { 
    test(); 
    return 0; 
} 

실행 위의 인쇄 : 그것의 기본 형식은 3 :(

있는 동안

Class: TCppComp - Total Props:3 
    AAAA 
    Name 
    Tag 
    Class: @%Mixin$8TCppComp% - Total Props:0 

IOW, 믹스 인이 '0'출판 속성으로 나타 나는 스트리밍 정기적 복용을 의심 이 카운트에 의존하기 때문에 상속 된 속성이 설정에 기록되지 않습니다.

런타임에 생성 된 설명자를 조정할 것을 고려했지만 _TEXT에 작성 했으므로 DEP를 트리거합니다.

올바른 숫자를 계산할 수있는 방법이 있는지 알아보기 위해 PropCount를 계산하는 논리를 살펴 보겠습니다. 시간이 허락한다면, 이것을 위해 QC를 열어주세요 : 이제 내가 밑을 들여다 보았으므로 기대했던대로 작동하도록 많은 노력을 기울일 필요가 없다고 생각합니다.

건배,

Bruneau

PS : 내 샘플에서는 심지어 믹스 인이 속성을 게시했고, 컴파일러가 해당 속성에 대한 정확한 설명을 생성; 그러나, 총계는 아직도 0이었다.

+0

감사합니다. Bruneau - 훌륭한 답변이며, 여기에서 만나서 정말 반가워요! – Roddy

+0

에 로그인 QC : http://qc.embarcadero.com/wc/qcmain.aspx?d=90446 – Roddy

+0

또한 E2242 문제와 비슷한 문제가 발생했습니다 : http : // qc로보고되었습니다. .embarcadero.com/wc/qcmain.aspx? d = 67683 – Roddy

관련 문제