IT TIP

C ++에서 클래스를 다른 클래스에서 상속하는 것으로 앞으로 선언 할 수 있습니까?

itqueen 2020. 12. 4. 21:40
반응형

C ++에서 클래스를 다른 클래스에서 상속하는 것으로 앞으로 선언 할 수 있습니까?


나는 내가 할 수 있다는 것을 안다.

class Foo;

하지만 다음과 같이 클래스를 다른 클래스에서 상속하도록 전달할 수 있습니다.

class Bar {};

class Foo: public Bar;

사용 사례의 예로는 공변 참조 반환 유형이 있습니다.

// somewhere.h
class RA {}
class RB : public RA {}

... 그리고 어딘가에 포함되지 않은 다른 헤더에 .h

// other.h
class RA;

class A {
 public:
  virtual RA* Foo();  // this only needs the forward deceleration
}

class RB : public RA; // invalid but...

class B {
 public:
  virtual RB* Foo();  // 
}

유일한 정보는 컴파일러 한다 의 선언을 처리해야 RB* B:Foo()IS RBRA공용 기본 클래스로합니다. .h에서 반환 값에 대한 일종의 역 참조를 수행하려는 경우 분명히 어딘가에 필요합니다 Foo. 그러나 일부 클라이언트가를 호출하지 않는 경우 Foo어딘가에 포함 할 이유가 없으므로 컴파일 속도가 크게 빨라질 수 있습니다.


포워드 선언은 그 이름을 가진 클래스가 존재하고 다른 곳에서 선언되고 정의 될 것임을 컴파일러에게 알리는 데만 유용합니다. 컴파일러가 클래스에 대한 컨텍스트 정보를 필요로하는 경우에 사용할 수 없으며, 클래스에 대해 조금만 알려주기 위해 컴파일러에 사용할 수도 없습니다. (일반적으로 매개 변수 또는 반환 값과 같이 다른 컨텍스트없이 해당 클래스를 참조 할 때만 forward 선언을 사용할 수 있습니다.)

따라서 Foo를 선언하는 데 사용하는 시나리오에서는 Bar를 포워드 선언 할 수 없으며 기본 클래스를 포함하는 포워드 선언을 갖는 것은 말이되지 않습니다. 아무것도?


포워드 선언은 정의가 아니라 선언입니다. 따라서 클래스 선언이 필요한 모든 것 (해당 클래스에 대한 포인터 등)은 포워드 선언 만 필요합니다. 그러나 정의가 필요한 모든 것 (즉, 클래스의 실제 구조를 알아야하는 경우)은 순방향 선언만으로 작동하지 않습니다.

파생 클래스는 부모가 존재한다는 것뿐만 아니라 부모의 구조를 확실히 알아야하므로 앞으로 선언하는 것만으로는 충분하지 않습니다.


포인터 만 다루더라도 상속을 전달하는 것은 불가능합니다. 포인터 간의 변환을 처리 할 때 컴파일러는 변환을 올바르게 수행하기 위해 클래스의 세부 사항을 알아야하는 경우가 있습니다. 다중 상속이있는 경우입니다. (단일 상속 만 사용하지만 언어의 일부가 아닌 계층 구조의 일부 부분을 특수한 경우에 사용할 수 있습니다.)

다음과 같은 사소한 경우를 고려하십시오.

#include <stdio.h>
class A { int x; };
class B { int y; };
class C: public A, public B { int z; };
void main()
{ 
    C c; A *pa = &c; B *pb = &c; C *pc = &c; 
    printf("A: %p, B: %p, C: %p\n", pa, pb, pc);
}

내가받은 출력 (32 비트 Visual Studio 2010 사용)은 다음과 같습니다.

A: 0018F748, B: 0018F74C, C: 0018F748

따라서 다중 상속의 경우 관련 포인터간에 변환 할 때 컴파일러는 올바른 변환을 위해 포인터 산술을 삽입해야합니다.

이것이 포인터 만 다루더라도 상속을 선언 할 수없는 이유입니다.

As for why it would be useful, it would improve compile times when you do want to make use of co-variant return types instead of using casts. For example this will not compile:

class RA;
class A             { public: virtual RA *fooRet(); };
class RB;
class B : public A  { public: virtual RB *fooRet(); };

But this will:

class RA;
class A             { public: virtual RA *fooRet(); };
class RA { int x; };
class RB : public RA{ int y; };
class B : public A  { public: virtual RB *fooRet(); };

This is useful when you have objects of type B (not pointers or references). In this case the compiler is smart enough to use a direct function call, and you can use the return type of RB* directly without casting. In this case, usually I go ahead and make the return type RA * and do a static cast on the return value.


I don't think it's useful. Consider: you have defined a class, Bar:

class Bar {
public:
    void frob();
};

Now you declare a class Foo:

class Foo;

All you can do with Foo is construct a pointer to it. Now, suppose you add the information that Foo is derived from Bar:

class Foo: public Bar;

What can you now do that you couldn't do before? I think that all you can do is accept a pointer to Foo and cast it into a pointer to Bar, then use that pointer.

void frob(Foo* f) {
    Bar *b = (Bar)f;
    b->frob();
}

However, you must have generated the pointer elsewhere, so you could have just accepted a pointer to Bar instead.

void frob(Bar* b) {
    b->frob();
}

참고URL : https://stackoverflow.com/questions/2159390/in-c-is-it-possible-to-forward-declare-a-class-as-inheriting-from-another-cla

반응형