문제

C#의 클래스 확장 메소드와 같은 원래 클래스 정의 (예 : .lib 포함 클래스 및 해당 .h 파일)를 수정하지 않고 클래스에 새로운 방법을 추가 할 수있는 방법이 있습니까?

도움이 되었습니까?

해결책

C ++에는 그러한 기능이 없습니다.

다른 답변에서 언급했듯이 일반적인 해결 방법은 다음과 같습니다.

  • 실제 구현 클래스를 숨기기 위해 공장이있는 파생 클래스 정의
  • 정의 a 데코레이터 수업
  • 클래스의 인스턴스에서 작동하는 비 멤버 기능 정의

다른 팁

아니요, C ++에서는 할 수 없습니다.

이와 같은 것을 달성하려면 두 가지 옵션이 있습니다.

  • 수업에서 상속받을 수 있습니다 (옵션 인 경우 상속을 허용하기 위해 클래스가 작성되지 않았기 때문에 합법적이지 않을 수 있습니다).
  • 동일한 인터페이스 + 새 메소드를 갖는 자신의 래퍼 클래스를 작성하고 확장하려는 방법을 위임 할 수 있습니다.

나는 대표단 접근법을 선호합니다.

C# 클래스 확장 방법은 대부분 구문 설탕입니다. 자유 함수 (즉, 첫 번째 매개 변수로서 클래스에 대한 참조 또는 지속적인 참조 기능을 갖춘 함수)로 동일한 기능을 얻습니다. 이것은 STL에 적합하기 때문에 수업에 적합하지 않습니까?

C ++에서는 무료 기능을 사용할 수 있지만 때로는 확장 방법이 많은 기능을 함께 둥지를 틀면 더 잘 작동합니다. 이 C# 코드를 살펴보십시오.

var r = numbers.Where(x => x > 2).Select(x => x * x);

무료 기능을 사용하여 C ++로 이것을 작성하려면 다음과 같습니다.

auto r = select(where(numbers, [](int x) { return x > 2; }), [](int x) { return x * x; });

이것은 읽기가 어렵을뿐만 아니라 쓰기가 어렵습니다. 이것을 해결하는 일반적인 방법은 파이프 가능 함수라고하는 것을 만드는 것입니다. 이러한 기능은 과부하로 만들어집니다 | 파이프 연산자 (실제로 OR 운영자). 따라서 위의 코드는 다음과 같이 작성 될 수 있습니다.

auto r = numbers | where([](int x) { return x > 2; }) | select([](int x) { return x * x; });

읽고 쓰기가 훨씬 쉽습니다. 많은 라이브러리는 범위에 Pipable Function을 사용하지만 다른 클래스로도 확장 될 수 있습니다. 부스트는 그것을 사용합니다 범위 도서관, Pstade 오븐 그것을 사용하고, 또한이 c ++도 사용합니다 LINQ 도서관도 사용합니다.

자신의 파이프 기능을 작성하려면 그렇게하는 방법을 설명하십시오. 여기. 그러나 다른 라이브러리는 기능 어댑터를 더 쉽게 할 수 있도록 기능 어댑터를 제공합니다. Pstade Egg에는 a 파이프 가능한 어댑터, 및 LINQ를 제공합니다 range_extension 최소한 범위에 대한 파이프 가능 함수를 생성하는 어댑터.

LINQ를 사용하면 먼저 다음과 같은 기능 객체로 기능을 만듭니다.

struct contains_t
{
    template<class Range, class T>
    bool operator()(Range && r, T && x) const
    { return (r | linq::find(x)) != boost::end(r); };
};

그런 다음 다음과 같은 정적 초기화를 사용하여 기능을 초기화합니다.

range_extension<contains_t> contains = {};

그런 다음 다음과 같은 파이프 기능을 사용할 수 있습니다.

if (numbers | contains(5)) printf("We have a 5");

일반적으로 그렇지 않습니다. 그러나 라이브러리가 확장이 필요한 클래스 인스턴스를 생성하지 않고 클래스 인스턴스를 생성하고 확장자가 필요한 앱의 모든 장소를 수정할 수있는 경우 다음과 같은 방법이 있습니다.

  • 클래스 인스턴스가 필요한 모든 장소에서 호출되는 공장 기능을 작성하고 인스턴스에 대한 포인터를 반환합니다 (Google 디자인 패턴 공장, ...).
  • 원하는 확장자로 파생 클래스를 만듭니다.
  • 공장 함수가 원래 클래스 대신 파생 클래스를 반환하게하십시오.

예시:


    class derivedClass: public originalClass { /* ... */};

    originalClass* createOriginalClassInstance()
    {
         return new derivedClass();
    }
  • 확장에 액세스해야 할 때마다 원본 캐스트를 파생 클래스로 캐스트해야합니다.

이것은 Glen이 제안한 "상속"방법을 구현하는 방법입니다. Glen의 "인터페이스 동일한 래퍼 클래스"메소드는 이론적 관점에서도 매우 훌륭하지만 약간 다른 속성을 가지고있어 귀하의 경우에 작동 할 가능성이 줄어 듭니다.

수행 할 수있는 한 가지 방법이 있습니다. 그리고 그것은 당신의 요구 사항을 조금 완화하는 것입니다. C ++에서 사람들은 종종 클래스의 인터페이스가 회원 기능뿐만 아니라 수업에서 작동하는 모든 기능.

즉, 매개 변수로 클래스를 제공 할 수있는 비회원 함수는 인터페이스의 일부로 간주되어야합니다.

예를 들어, std::find() 또는 std::sort() 인터페이스의 일부입니다 std::vector, 비록 그들이 수업의 회원이 아니더라도.

이 정의를 수락하면 비 멤버 함수를 추가하여 항상 클래스를 확장 할 수 있습니다.

이진 형식의 클래스 파일에 메소드 나 데이터를 물리적으로 추가 할 수 없습니다. 그러나 확장 클래스를 작성하여 해당 클래스의 객체에 메소드 및 데이터 (기능 및 상태)를 추가 할 수 있습니다. 이것은 간단하지 않으며 메타 객체 프로토콜과 인터페이스 기반 프로그래밍이 필요합니다. C ++에서이를 달성하기 위해 많은 노력을 기울여야합니다. 상자에서 반사를 지원하지 않기 때문입니다. 원래 클래스 객체 포인터를 통해 새 확장 클래스에서 구현 한 인터페이스를 쿼리 할 때 이러한 구현에서 메타 객체 구현은 런타임에 생성하는 확장 클래스의 메타 클래스 객체를 통해 인터페이스 포인터를 반환합니다. 이것은 몇 개의 사용자 정의 가능한 (플러그인 기반) 소프트웨어 응용 프로그램 프레임 워크 작동 수입니다. 그러나 객체 관계가 설명되고 원래 및 확장 클래스 객체에 대한 올바른 인터페이스 포인터를 제공하는 사전을 사용하여 모든 클래스에 대해 메타 객체를 주입하기 위해 많은 다른 MOP 메커니즘이 Meta Object를 시동하도록 작성해야한다는 것을 기억해야합니다. Dassault Systemes의 CATIA V5는 CAA V5라는 아키텍처로 작성되었으며 원하는 기능으로 새로운 확장 클래스를 작성하여 기존 구성 요소를 확장 할 수 있습니다.

죄송합니다. 코드가 OBJ에 있으면 변경할 수 없습니다. VC에서이를 수행 할 수 있다면 부분 클래스는 이미 지원됩니다. 그러나 한 가지 예외가 있지만, Cout <<이 STL에서 구현되는 방식과 마찬가지로 전역 기능을 사용하여 운영자 방법을 확장 할 수 있습니다.

물론 넌 할 수있어:


template <typename Ext>
class Class: public Ext { /* ... */ };

그렇다고해서 최선의 접근 방식이라는 의미는 아닙니다.

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