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 RB
가 RA
공용 기본 클래스로합니다. .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();
}
'IT TIP' 카테고리의 다른 글
TypeCasting의 성능 (0) | 2020.12.04 |
---|---|
좋아하는 SQLPLUS 팁과 요령 (0) | 2020.12.04 |
Java의 열거 형에 함수를 추가 할 수 있습니까? (0) | 2020.12.04 |
상속을 사용하는 이유는 무엇입니까? (0) | 2020.12.04 |
nginx 502 잘못된 게이트웨이 (0) | 2020.12.04 |