program tip

C ++에서 업 캐스팅은 언제 불법입니까?

radiobox 2020. 12. 31. 08:10
반응형

C ++에서 업 캐스팅은 언제 불법입니까?


나는 특히 C ++에서 업 캐스팅과 다운 캐스팅의 일반적인 차이점을 이해하고 있다고 확신합니다. 기본 클래스 포인터를 파생 클래스 포인터로 캐스팅하면 가리키는 기본 클래스 개체에 파생 클래스의 모든 멤버가 있다고 가정하므로 항상 다운 캐스트 할 수는 없음을 이해합니다.

학기 초에 교수님 께서 수업 시간에 C ++로 업 캐스트하는 것도 불법이라고 말씀 하셨는데, 메모에서 그 이유를 놓친 것 같고 언제 이런 일이 발생했는지 기억이 나지 않습니다.

C ++에서 업 캐스트하는 것은 언제 불법입니까?


"불법"이란 잘못된 형식을 의미하는 경우 기본 클래스에 액세스 할 수 없거나 모호한 경우 불법입니다.

  • 예를 들어 기본 클래스가 비공개 인 경우 액세스 할 수 없습니다.

    class A {};
    class B : A {};
    ...
    B b;
    A *pa = &b; // ERROR: base class is inaccessible
    

    C ++ 11에서도 C 스타일 캐스트는 액세스 보호를 "돌파"하고 공식적으로 올바른 업 캐스트를 수행 할 수 있습니다.

    A *pa = (A *) &b; // OK, not a `reinterpret_cast`, but a valid upcast
    

    물론 이러한 사용은 피해야합니다.

  • 소스 유형에 대상 유형의 여러 기본 하위 객체가 포함되어있는 경우 (다중 상속을 통해) 모호합니다.

    class A {};
    class B : public A {};
    class C : public A {};
    class D : public B, public C {};
    
    D d;
    A *pa = &d; // ERROR: base class is ambiguous
    

    이러한 경우 업 캐스트는 중간 업 캐스트가있는 원하는 업 캐스트 경로를베이스가 더 이상 모호하지 않은 지점까지 명시 적으로 "보행"하여 수행 할 수 있습니다.

    B* pb = &d;
    A* pa = pb; // OK: points to 'D::B::A' subobject
    

기본 클래스가 모호한 경우 (다른 경로를 통해 두 번 이상 상 속됨) 한 단계로 업 캐스트를 수행 할 수 없습니다.

기본 클래스에 액세스 할 수없는 경우 업 캐스트하는 유일한 방법은 C 스타일 캐스트를 사용하는 것입니다. 이것은 그 캐스트의 특별한 경우이며 일을 할 수있는 유일한 사람입니다. 기본적으로는 static_cast접근성에 의해 제한되지 않는 것처럼 작동 합니다.


Standardese.

C ++ 11 §5.4 / 4 :

… [a C cast] static_cast에서 다음 상황에서 a 수행 하면 기본 클래스에 액세스 할 수없는 경우에도 변환이 유효합니다.

  • 파생 클래스 유형의 개체에 대한 포인터 또는 파생 클래스 유형의 lvalue 또는 rvalue는 각각 명확한 기본 클래스 유형에 대한 포인터 또는 참조로 명시 적으로 변환 될 수 있습니다.
  • 파생 클래스 형식의 멤버에 대한 포인터는 모호하지 않은 비가 상 기본 클래스 형식의 멤버에 대한 포인터로 명시 적으로 변환 될 수 있습니다.
  • 모호하지 않은 비가 상 기본 클래스 유형의 객체에 대한 포인터, 모호하지 않은 비가 상 기본 클래스 유형의 glvalue 또는 모호하지 않은 비가 상 기본 클래스 유형의 멤버에 대한 포인터는 명시 적으로 포인터로 변환 될 수 있습니다. 참조 또는 파생 클래스 형식의 멤버에 대한 포인터입니다.

모호성의 예 :

struct Base {};
struct M1: Base {};
struct M2: Base {};
struct Derived: M1, M2 {};

auto main() -> int
{
    Derived d;
    //static_cast<Base&>( d );                      //! Ambiguous
    static_cast<Base&>( static_cast<M2&>( d ) );    // OK
}

캐스트에서 (일반적으로) 주소 조정이있는 액세스 할 수없는베이스의 예 :

struct Base { int value; Base( int x ): value( x ) {} };

class Derived
    : private Base
{
public:
    virtual ~Derived() {}       // Just to involve an address adjustment.
    Derived(): Base( 42 ) {}
};

#include <iostream>
using namespace std;

auto main() -> int
{
    Derived d;
    Base& b = (Base&) d;
    cout << "Derived at " << &d << ", base at " << &b << endl;
    cout << b.value << endl;
};

업 캐스팅이 C ++에서 잘못 구성되는 두 가지 경우가 있습니다 (컴파일시 진단 됨).

  1. 문제의 기본 클래스에 액세스 할 수 없습니다 .

    class base {};
    class derived : base {};
    
    int main() {
        derived x;
        base& y = x; // invalid because not accessible.
        // Solution: C-style cast (as static_cast without access-check)
        base& y1 = (base&)x;
    }
    
  2. 문제의 기본 클래스 하위 개체는 명확하지 않습니다 .

    class base {};
    struct A1 : base {};
    struct A2 : base {};
    
    struct derived : A1, A2 {};
    int main() {
        derived x;
        base& y = x; // invalid because ambiguous.
        // Solution 1, scope resolution:
        base& y1 = static_cast<A1::base&>(x);
        base& y2 = static_cast<A2::base&>(x);
        // Solution 2, intermediate unambiguous steps:
        A1& a1 = x;
        A2& a2 = x;
        base& ya1 = a1;
        base& ya2 = a2;
    }
    

참조 URL : https://stackoverflow.com/questions/26982648/when-is-upcasting-illegal-in-c

반응형