C ++에서 "super"사용


203

내 코딩 스타일에는 다음 관용구가 포함됩니다.

class Derived : public Base
{
   public :
      typedef Base super; // note that it could be hidden in
                          // protected/private section, instead

      // Etc.
} ;

이를 통해 생성자에서 "super"를 Base의 별칭으로 사용할 수 있습니다.

Derived(int i, int j)
   : super(i), J(j)
{
}

또는 재정의 된 버전 내의 기본 클래스에서 메서드를 호출 할 때도 :

void Derived::foo()
{
   super::foo() ;

   // ... And then, do something else
}

심지어 체인으로 묶을 수도 있습니다 (그러나 여전히 그 용도를 찾아야합니다).

class DerivedDerived : public Derived
{
   public :
      typedef Derived super; // note that it could be hidden in
                             // protected/private section, instead

      // Etc.
} ;

void DerivedDerived::bar()
{
   super::bar() ; // will call Derived::bar
   super::super::bar ; // will call Base::bar

   // ... And then, do something else
}

어쨌든, "typedef super"의 사용은 예를 들어 Base가 장황하고 /하거나 템플릿 일 때 매우 유용합니다.

사실 super는 C #뿐만 아니라 Java에서도 구현됩니다 (잘못된 경우가 아니라면 "base"라고합니다). 그러나 C ++에는이 키워드가 없습니다.

그래서 내 질문 :

  • 이 타입 정의 사용은 작업 코드에서 보지 못했습니까?
  • typedef super Ok를 사용합니까 (즉, 사용하지 않을 강력한 이유가 있습니까)?
  • "super"가 좋은 것이어야합니까, C ++에서 다소 표준화되어야합니까, 아니면 typedef를 통해 이미 사용하고 있습니까?

편집 : Roddy는 typedef가 비공개이어야한다는 사실을 언급했습니다. 이것은 파생 클래스가 클래스를 다시 선언하지 않으면 사용할 수 없다는 것을 의미합니다. 그러나 그것은 그것이 super :: super chaining을 막을 것이라고 생각합니다 (그러나 누가 울겠습니까?).

편집 2 : "슈퍼"를 대량으로 사용한 지 몇 개월이 지나서 나는 Roddy의 견해에 전적으로 동의합니다. "슈퍼"는 사적이어야합니다. 나는 그의 대답을 두 번 찬성했지만 나는 할 수 없다고 생각합니다.


대박! 정확히 내가 찾던 것. 지금까지이 기술을 사용해야했다고 생각하지 마십시오. 크로스 플랫폼 코드를위한 탁월한 솔루션입니다.
AlanKley

6
super처럼 보이고 Java나쁘지는 않지만 ...하지만 C++다중 상속을 지원합니다.
ST3

2
@ user2623967 : 맞습니다. 단순한 상속의 경우 하나의 "슈퍼"이면 충분합니다. 이제 다중 상속이있는 경우 "superA", "superB"등을 사용하는 것이 좋은 솔루션입니다. 한 구현에서 다른 구현으로 메소드를 호출하려면 원하는 구현을 알려야합니다. "super"와 같은 typedef를 사용하면 쉽게 쓸 수 있고 쓸 수있는 이름을 제공 할 수 있습니다 (예를 들어, MyFirstBase<MyString, MyStruct<MyData, MyValue>>어디에나 쓰는 대신 )
paercebal

템플릿에서 상속 할 때 참조 할 때 템플릿 인수를 포함 할 필요가 없습니다. 예를 들어 : template <class baz> struct Foo {...void bar() {...} ...}; struct Foo2: Foo<AnnoyinglyLongListOfArguments> { void bar2() { ... Foo::bar(); ...} };이것은 gcc 9.1 --std = c ++ 1y (c ++ 14)에서 나에게 효과적이었습니다.
Thanasis Papoutsidakis

1
... 음, 수정. 14
개가

답변:


151

Bjarne Stroustrup 은 C ++의 Design and Evolution에서 C ++super처음 표준화 될 때 ISO C ++ 표준위원회에서 키워드로 간주 했다고 언급했습니다 .

Dag Bruck는 기본 클래스를 "상 속됨"이라고하며이 확장을 제안했습니다. 이 제안은 다중 상속 문제를 언급했으며 모호한 용도로 플래그를 지정했을 것입니다. Stroustrup조차도 확신했다.

토론 후 Dag Bruck (예, 제안을 한 사람)은 제안이 구현 가능하고 기술적으로 건전하며 주요 결함이 없으며 다중 상속을 처리했다고 썼습니다. 다른 한편으로, 벅에 대한 강타가 충분하지 않았으므로위원회는 더 어려운 문제를 처리해야합니다.

마이클 타이 만 (Michael Tiemann)이 늦게 도착한 후,이 게시물에서 요구 한 것과 같은 기술을 사용하여 typedef의 슈퍼가 잘 작동한다는 것을 보여주었습니다.

따라서, 이것은 아마도 표준화되지 않을 것입니다.

사본이 없으면 Design and Evolution 은 커버 가격으로 가치가 있습니다. 중고 사본은 약 $ 10에 구입할 수 있습니다.


5
D & E는 실제로 좋은 책입니다. 그러나 다시 읽어야 할 것 같습니다. 두 이야기는 기억 나지 않습니다.
Michael Burr

2
D & E에서 논의되지 않은 세 가지 특징을 기억합니다. 이것은 첫 번째 (이야기를 찾기 위해 색인에서 "Michael Tiemann"을 찾고) 2 주 규칙은 두 번째 (지수에서 "2 주 규칙"을 찾습니다)이며 세 번째는 매개 변수 ( " 색인에서 명명 된 인수 ").
Max Lybbert

12
typedef기술 에는 큰 결함이 있습니다 . DRY를 존중하지 않습니다. 유일한 방법은 못생긴 매크로를 사용하여 클래스를 선언하는 것입니다. 상속하면 기본은 긴 다중 매개 변수 템플릿 클래스이거나 더 나쁠 수 있습니다. (예 : 멀티 클래스) 다시 한 번 다시 작성해야합니다. 마지막으로 템플릿 클래스 인수가있는 템플릿 기반에 큰 문제가 있습니다. 이 경우 수퍼는 템플릿입니다 (템플릿을 표시하지 않음). 형식을 지정할 수 없습니다. C ++ 11 에서도이 using경우 가 필요 합니다.
v.oddou

105

나는 항상 슈퍼보다는 "상속 된"을 사용했습니다. (아마도 델파이 배경으로 인해), 클래스에서 '상속 된'이 잘못 생략되었지만 하위 클래스에서 사용하려고 할 때 문제를 피하기 위해 항상 개인용으로 만듭니다 .

class MyClass : public MyBase
{
private:  // Prevents erroneous use by other classes.
  typedef MyBase inherited;
...

새 클래스를 만들기위한 표준 '코드 템플릿'에는 typedef가 포함되어 있으므로 실수로 생략 할 기회가 거의 없습니다.

연쇄 "super :: super"제안은 좋은 생각이라고 생각하지 않습니다. 그렇게하는 경우 특정 계층 구조와 매우 밀접하게 연결되어 있으며 변경하면 문제가 발생할 수 있습니다.


2
chaining super :: super와 관련하여 질문에서 언급했듯이 여전히 흥미로운 사용법을 찾아야합니다. 지금은 해킹으로 만 볼 수 있지만 Java와의 차이점 ( "슈퍼"를 연결할 수없는 경우)에 대해서는 언급 할 가치가 있습니다.
paercebal

4
몇 달 후, 나는 당신의 관점으로 전환되었습니다 (그리고 당신이 언급 한 것처럼 잊혀진 "슈퍼"때문에 버그가있었습니다 ...) 당신은 체인을 포함하여 당신의 대답에 아주 맞습니다. ^ _ ^ ...
paercebal 2016 년

부모 클래스 메소드를 호출하기 위해 이것을 어떻게 사용합니까?
mLstudent33

virtual여기에 표시된 대로 모든 기본 클래스 메소드를 선언해야 함을 의미합니까? martinbroadhurst.com/typedef-super.html
mLstudent33

36

이것의 한 가지 문제는 파생 클래스에 대해 super를 재정의하는 것을 잊어 버린 경우 super :: something에 대한 호출은 정상적으로 컴파일되지만 원하는 함수를 호출하지는 않는다는 것입니다.

예를 들면 다음과 같습니다.

class Base
{
public:  virtual void foo() { ... }
};

class Derived: public Base
{
public:
    typedef Base super;
    virtual void foo()
    {
        super::foo();   // call superclass implementation

        // do other stuff
        ...
    }
};

class DerivedAgain: public Derived
{
public:
    virtual void foo()
    {
        // Call superclass function
        super::foo();    // oops, calls Base::foo() rather than Derived::foo()

        ...
    }
};

Martin York이이 답변에 대한 의견에서 지적한 것처럼이 문제는 typedef를 public 또는 protected가 아닌 private로 만들어 제거 할 수 있습니다.


발언 감사합니다. 이 부작용은 나의 통지를 피했다. 아마도 생성자 사용을 위해 컴파일되지는 않지만 다른 곳에서는 버그가있을 것입니다.
paercebal

5
그러나 private typedef는 원래 게시물에서 언급 한 체인 사용을 방지합니다.
AnT

1
이 정확한 버그로 실행하면 :(이 질문에 나를 이끌 것입니다
스티브 Vermeulen에게

그래서 사용하는 super1기본과 super2유래에? DerivedAgain은 둘 다 사용할 수 있습니까?
mLstudent33

20

FWIW Microsoft는 컴파일러 에 __super 에 대한 확장을 추가했습니다 .


여기서 몇몇 개발자는 __super를 사용하기 시작했습니다. 처음에 나는 그것이 "잘못"과 "비표준"이라고 느꼈기 때문에 뒤로 밀렸다. 그러나 나는 그것을 사랑하기 위해 자랐습니다.
Aardvark

8
Windows 앱을 만들고 있는데 __super 확장 프로그램을 좋아합니다. 표준위원회가 여기에 언급 된 typedef 트릭을 선호하여 거부했다고 슬프다.이 typedef 트릭은 훌륭하지만 상속 계층 구조를 변경할 때 컴파일러 키워드보다 더 많은 유지 관리가 필요하고 여러 상속을 올바르게 처리합니다 (2 개 필요 없음) super1 및 super2와 같은 typedef). 요컨대, 나는 MS 확장이 매우 유용하다는 다른 의견에 동의하며 Visual Studio를 독점적으로 사용하는 사람은 그것을 사용하는 것이 좋습니다.
Brian

15

Super (또는 상속 된)는 매우 좋은 것입니다. Base와 Derived 사이에 다른 상속 계층을 고정해야하는 경우 다음 두 가지만 변경하면됩니다. 1. "class Base : foo"및 2. typedef

내가 올바르게 기억한다면, C ++ 표준위원회는 Michael Tiemann이이 typedef 트릭이 효과가 있다고 지적 할 때까지 이것에 대한 키워드 추가를 고려하고있었습니다.

다중 상속에 관해서는 프로그래머 제어하에 있기 때문에 super1 및 super2 또는 무엇이든 원하는대로 할 수 있습니다.


13

방금 다른 해결 방법을 찾았습니다. 오늘 날 typedef 접근법에 큰 문제가 있습니다.

  • typedef에는 클래스 이름의 정확한 사본이 필요합니다. 누군가 클래스 이름을 변경했지만 typedef를 변경하지 않으면 문제가 발생합니다.

그래서 나는 매우 간단한 템플릿을 사용하여 더 나은 솔루션을 생각해 냈습니다.

template <class C>
struct MakeAlias : C
{ 
    typedef C BaseAlias;
};

그래서 지금 대신

class Derived : public Base
{
private:
    typedef Base Super;
};

당신은 가지고

class Derived : public MakeAlias<Base>
{
    // Can refer to Base as BaseAlias here
};

이 경우 BaseAlias비공개가 아니며 다른 개발자에게 경고 해야하는 유형 이름을 선택하여 부주의 한 사용을 방지하려고했습니다.


4
publicRoddy 'sKristopher의 답변 에서 언급 한 버그에 개방되어 있기 때문에 alias는 단점입니다 (예 : 실수로 Derived대신 할 수 있음 MakeAlias<Derived>)
Alexander Malakhov

3
또한 이니셜 라이저 목록의 기본 클래스 생성자에 액세스 할 수 없습니다. (이것은에서 상속 생성자를 사용하여 C ++에서 11 보상 될 수 MakeAlias또는 완벽한 전달,하지만 참조 할 필요합니까 MakeAlias<BaseAlias>생성자보다는 참조 C직접 생성자의.)
아담 H. 피터슨

12

나는 이것을 전에 본 것을 기억하지 못하지만 언뜻보기에 나는 그것을 좋아한다. Ferruccio가 지적한 바와 같이 MI에서는 잘 작동하지 않지만 MI는 규칙보다 예외이며 유용하기 위해 어디에서나 사용할 수 있어야한다고 말하는 것은 없습니다.


6
"어디서나 유용하게 사용할 수 있어야하는 것은 없다"라는 문구를 찬성하라.
Tanktalus

1
동의했다. 쓸모있다. 템플릿을 통해 typedef를 생성하는 방법이 있는지 확인하기 위해 boost type traits 라이브러리를보고있었습니다. 불행히도, 당신이 할 수없는 것 같습니다.
Ferruccio

9

이 관용구가 많은 코드에서 사용되는 것을 보았고 Boost의 라이브러리 어딘가에서 보았을 것입니다. 그러나 가장 일반적인 이름을 기억하는 한 대신 base(또는 Base)super .

이 관용구는 템플릿 클래스로 작업 할 때 특히 유용합니다. 예를 들어 ( 실제 프로젝트에서 ) 다음 클래스를 고려하십시오 .

template <typename TText, typename TSpec>
class Finder<Index<TText, PizzaChili<TSpec> >, PizzaChiliFinder>
    : public Finder<Index<TText, PizzaChili<TSpec> >, Default>
{
    typedef Finder<Index<TText, PizzaChili<TSpec> >, Default> TBase;
    // …
}

재미있는 이름은 신경 쓰지 마십시오. 여기서 중요한 점은 상속 체인이 형식 인수를 사용하여 컴파일 타임 다형성을 달성한다는 것입니다. 불행히도 이러한 템플릿의 중첩 수준은 상당히 높아집니다. 따라서 약어는 가독성 및 유지 관리에 중요합니다.


같은 이유로 최근에 "슈퍼"를 사용했습니다. 대중의 상속 재산은 다른 것을 다루기에는 너무 고통 스러웠다 ... :-) ...
paercebal


4

이 타입 정의 사용은 작업 코드에서 보지 못했습니까?

내가 작업하는 C ++ 코드 에서이 특정 패턴을 본 적이 없지만 그것이 존재하지 않는다는 것을 의미하지는 않습니다.

typedef super Ok를 사용합니까 (즉, 사용하지 않을 강력한 이유가 있습니까)?

다중 상속 (깨끗하게, 어쨌든)을 허용하지 않습니다.

"super"가 좋은 것이어야합니까, C ++에서 다소 표준화되어야합니까, 아니면 typedef를 통해 이미 사용하고 있습니까?

위에서 언급 한 이유로 (다중 상속) 아닙니다. 나열한 다른 언어에서 "super"가 표시되는 이유는 단일 상속 만 지원하기 때문에 "super"가 무엇을 말하는지 혼동하지 않기 때문입니다. 물론 그러한 언어에서는 유용하지만 실제로 C ++ 데이터 모델에는 자리가 없습니다.

아, 그리고 FYI : C ++ / CLI는이 개념을 "__super"키워드 형식으로 지원합니다. 그러나 C ++ / CLI는 다중 상속도 지원하지 않습니다.


4
카운터 포인트로서 Perl은 다중 상속 SUPER을 모두 가지고 있습니다 . 약간의 혼동이 있지만 VM이 무언가를 찾기 위해 수행하는 알고리즘이 명확하게 문서화되어 있습니다. 즉, MI가 여러 기본 클래스가 혼동이 발생할 수있는 동일한 방법을 제공하는 경우에는 거의 사용되지 않습니다.
Tanktalus

1
Microsoft Visual Studio는 CLI 용이든 아니든 C ++ 용 __super 키워드를 구현합니다. 상속 된 클래스 중 하나만이 올바른 서명 방법을 제공하는 경우 (Tanktalus에서 언급 한 가장 일반적인 경우) 올바른 선택 만 선택합니다. 두 개 이상의 상속 된 클래스가 함수 일치를 제공하면 작동하지 않으며 명시 적이어야합니다.
Brian

3

수퍼 클래스에 typedef를 사용하는 또 다른 이유는 객체의 상속에서 복잡한 템플릿을 사용할 때입니다.

예를 들어 :

template <typename T, size_t C, typename U>
class A
{ ... };

template <typename T>
class B : public A<T,99,T>
{ ... };

클래스 B에서는 A에 대한 typedef를 갖는 것이 이상적입니다. 그렇지 않으면 A의 멤버를 참조하려는 모든 곳에서 반복하여 붙어 있습니다.

이 경우 다중 상속으로도 작동 할 수 있지만 'super'라는 typedef가 없으면 'base_A_t'또는 이와 비슷한 이름이됩니다.

--jeffk ++


2

하루 전에 Turbo Pascal에서 C ++로 마이그레이션 한 후에도 동일한 방식으로 작동하는 Turbo Pascal "상속 된"키워드와 동등한 기능을 갖기 위해이 작업을 수행했습니다. 그러나 몇 년 동안 C ++로 프로그래밍 한 후에는 중단했습니다. 나는 그다지 필요하지 않다는 것을 알았습니다.


1

드문 지 아닌지는 모르겠지만 확실히 같은 일을 해냈습니다.

지적한 바와 같이, 언어 자체의이 부분을 만드는 데 어려움은 클래스가 다중 상속을 사용할 때입니다.


1

나는 때때로 이것을 사용합니다. 내가 기본 클래스 유형을 두 번 입력하는 것을 발견했을 때 나는 당신과 비슷한 typedef로 대체 할 것입니다.

나는 그것이 잘 사용할 수 있다고 생각합니다. 말하자면 기본 클래스가 템플릿 인 경우 입력을 저장할 수 있습니다. 또한 템플릿 클래스는 템플릿의 작동 방식에 대한 정책으로 작동하는 인수를 사용할 수 있습니다. 베이스의 인터페이스가 호환되는 한 모든 참조를 수정하지 않고도베이스 유형을 자유롭게 변경할 수 있습니다.

typedef를 통한 사용은 이미 충분하다고 생각합니다. 다중 상속은 많은 기본 클래스가 있다는 것을 의미하기 때문에 어쨌든 언어에 언어가 어떻게 구현되는지 알 수 없습니다. 따라서 논리적으로 생각하는 클래스가 가장 중요한 기본 클래스라고 생각할 때 typedef를 사용할 수 있습니다.


1

나는이 똑같은 문제를 해결하려고 노력했다. 나는 variadic 템플릿과 팩 확장을 사용하여 임의의 수의 부모를 허용하는 것과 같은 몇 가지 아이디어를 던졌지 만 'super0'및 'super1'과 같은 구현이 가능하다는 것을 깨달았습니다. 나는 그것을 시작하지 않아도되는 것보다 거의 유용하기 때문에 휴지통에 버렸습니다.

내 솔루션에는 도우미 클래스가 포함되며 다음 PrimaryParent과 같이 구현됩니다.

template<typename BaseClass>
class PrimaryParent : virtual public BaseClass
{
protected:
    using super = BaseClass;
public:
    template<typename ...ArgTypes>
    PrimaryParent<BaseClass>(ArgTypes... args) : BaseClass(args...){}
}

그런 다음 사용하려는 클래스는 다음과 같이 선언됩니다.

class MyObject : public PrimaryParent<SomeBaseClass>
{
public:
    MyObject() : PrimaryParent<SomeBaseClass>(SomeParams) {}
}

가상 상속을 사용할 필요 방지하기 위해 PrimaryParent에를 BaseClass, 가변 인자를 복용 생성자의 건설을 허용하는 데 사용됩니다 BaseClass.

뒤에서 그 이유 public의 상속 BaseClass으로는 PrimaryParent수 있도록하는 것입니다 MyObject의 상속을 통해 완벽하게 제어 할 수 있습니다BaseClass 그들 사이의 헬퍼 클래스에도 불구하고.

이것은 원하는 모든 클래스 superPrimaryParent도우미 클래스를 사용해야 하며 각 어린이는 하나의 클래스 PrimaryParent(따라서 이름) 만 상속받을 수 있음을 의미합니다.

이 메소드에 대한 또 다른 제한 사항 MyObject은에서 상속하는 하나의 클래스 만 상속 할 수 있으며이 클래스를 PrimaryParent사용하여 상속해야합니다 PrimaryParent. 여기 내가 의미하는 바가있다 :

class SomeOtherBase : public PrimaryParent<Ancestor>{}

class MixinClass {}

//Good
class BaseClass : public PrimaryParent<SomeOtherBase>, public MixinClass
{}


//Not Good (now 'super' is ambiguous)
class MyObject : public PrimaryParent<BaseClass>, public SomeOtherBase{}

//Also Not Good ('super' is again ambiguous)
class MyObject : public PrimaryParent<BaseClass>, public PrimaryParent<SomeOtherBase>{}

많은 수의 제한 사항과 모든 상속 사이에 중개인 클래스가 있기 때문에 이것을 옵션으로 폐기하기 전에 이러한 것들이 나쁘지 않습니다.

다중 상속은 강력한 도구이지만 대부분의 경우 기본 부모는 하나 뿐이며 다른 부모가 있으면 Mixin 클래스 또는 PrimaryParent어쨌든 상속하지 않는 클래스 일 수 있습니다 . 다중 상속이 여전히 필요한 경우 (많은 상황에서 상속 대신 객체를 정의하기 위해 컴포지션을 사용하는 것이 도움이되지만) super클래스에서 명시 적으로 정의하고 에서 상속하지 않는 것보다 PrimaryParent.

super모든 클래스에서 정의해야한다는 아이디어 는 상속 기반 별칭을 명확하게 사용 하여 데이터가 이동 해야하는 클래스 본문 대신 클래스 정의 행에 머무를 PrimaryParent수 있다는 점을 사용하여 매우 매력적이지 않습니다 super.

그래도 나일지도 모른다.

물론 모든 상황은 다르지만 사용할 옵션을 결정할 때 내가 말한 것을 고려하십시오.


1

슈퍼가 전화베이스를 의미하지 않는다는 것을 보여주는 주석이있는 현재 코드를 제외하고는 많이 말하지 않을 것입니다!

super != base.

요컨대, "슈퍼"란 무엇을 의미합니까? "base"는 무엇을 의미합니까?

  1. 슈퍼 수단, 메소드의 마지막 구현 자 호출 (기본 메소드 아님)
  2. 기본은 다중 상속에서 기본 기반 인 클래스를 선택하는 것을 의미합니다.

이 두 규칙은 typedef 클래스에 적용됩니다.

도서관 구현 자와 도서관 사용자를 고려하십시오. 누가 슈퍼이고 누가 기본입니까?

자세한 내용은 IDE에 복사 붙여 넣기를위한 작업 코드입니다.

#include <iostream>

// Library defiens 4 classes in typical library class hierarchy
class Abstract
{
public:
    virtual void f() = 0;
};

class LibraryBase1 :
    virtual public Abstract
{
public:
    void f() override
    {
        std::cout << "Base1" << std::endl;
    }
};

class LibraryBase2 :
    virtual public Abstract
{
public:
    void f() override
    {
        std::cout << "Base2" << std::endl;
    }
};

class LibraryDerivate :
    public LibraryBase1,
    public LibraryBase2
{
    // base is meaningfull only for this class,
    // this class decides who is my base in multiple inheritance
private:
    using base = LibraryBase1;

protected:
    // this is super! base is not super but base!
    using super = LibraryDerivate;

public:
    void f() override
    {
        std::cout << "I'm super not my Base" << std::endl;
        std::cout << "Calling my *default* base: " << std::endl;
        base::f();
    }
};

// Library user
struct UserBase :
    public LibraryDerivate
{
protected:
    // NOTE: If user overrides f() he must update who is super, in one class before base!
    using super = UserBase; // this typedef is needed only so that most derived version
    // is called, which calls next super in hierarchy.
    // it's not needed here, just saying how to chain "super" calls if needed

    // NOTE: User can't call base, base is a concept private to each class, super is not.
private:
    using base = LibraryDerivate; // example of typedefing base.

};

struct UserDerived :
    public UserBase
{
    // NOTE: to typedef who is super here we would need to specify full name
    // when calling super method, but in this sample is it's not needed.

    // Good super is called, example of good super is last implementor of f()
    // example of bad super is calling base (but which base??)
    void f() override
    {
        super::f();
    }
};

int main()
{
    UserDerived derived;
    // derived calls super implementation because that's what
    // "super" is supposed to mean! super != base
    derived.f();

    // Yes it work with polymorphism!
    Abstract* pUser = new LibraryDerivate;
    pUser->f();

    Abstract* pUserBase = new UserBase;
    pUserBase->f();
}

또 다른 중요한 점은 다음과 같습니다.

  1. 다형성 호출 : 하향 호출
  2. 슈퍼 콜 : 위쪽으로 전화

내부에서 main()우리는 슈퍼 콜을 위쪽으로하는 다형성 콜 다운을 사용하지만 실제로는 유용하지 않지만 그 차이를 보여줍니다.



0

이것은 typedef 대신 매크로를 사용하는 방법입니다. 나는 이것이 C ++ 방식이 아니라는 것을 알고 있지만 계층 구조에서 가장 멀리있는 기본 클래스 만 상속 된 오프셋에서 작동 할 때 상속을 통해 반복자를 함께 연결할 때 편리 할 수 ​​있습니다.

예를 들면 다음과 같습니다.

// some header.h

#define CLASS some_iterator
#define SUPER_CLASS some_const_iterator
#define SUPER static_cast<SUPER_CLASS&>(*this)

template<typename T>
class CLASS : SUPER_CLASS {
   typedef CLASS<T> class_type;

   class_type& operator++();
};

template<typename T>
typename CLASS<T>::class_type CLASS<T>::operator++(
   int)
{
   class_type copy = *this;

   // Macro
   ++SUPER;

   // vs

   // Typedef
   // super::operator++();

   return copy;
}

#undef CLASS
#undef SUPER_CLASS
#undef SUPER

내가 사용하는 일반 설정을 사용하면 중복 코드가 있지만 상속 유형이 현재 클래스와 일치해야하므로 재정의 해야하는 상속 트리 간을 읽고 복사 / 붙여 넣기가 매우 쉽습니다.

superJava에서 보이는 동작을 복제하기 위해 소문자 를 사용할 수 있지만 코딩 스타일은 매크로에 모든 대문자를 사용하는 것입니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.