2013-02-11 3 views
5
class a //my base abstract class 
{ 
public: 
virtual void foo() = 0; 
}; 

class b : public a //my child class with new member object 
{ 
public: 
void foo() 
{} 
int obj; 
}; 

int main() 
{ 
b bee; 
a * ptr = &bee; 
ptr->obj; //ERROR: class a has no member named "obj" 
} 

내 질문은 하위 클래스 ("a")를 가리키는 기본 클래스 ("a")에 대한 포인터가있을 때 "obj" ") 객체? 캐스팅은 트릭을해야한다는 것을 알고 있지만 더 나은 솔루션을 찾고 있습니다.기본 abstact 클래스에 대한 포인터를 사용하여 하위 클래스 멤버에 액세스

+0

일부 컨텍스트가 도움이됩니다. 왜 그걸 원하니? 캐스팅이 옵션이 아니면 파생 클래스에서 해당 멤버에 대한 참조 또는 포인터를 반환하는 가상 함수를 재정의해야합니다. 그러나 일반적으로 캡슐화가 중단됩니다. 이렇게하면 기본 클래스에 대한 포인터를 통해 파생 클래스 멤버에 액세스하려는 이유가 다시 나타납니다. – Void

+0

@ Void 아마 맞아, 디자인을 바꾸어야 해. – user1873947

답변

7

dynamic_cast<> 연산자를 사용하면 a 포인터를 b 포인터로 변환 할 수 있습니다. 변환은 객체의 런타임 타입 ptrb입니다 가리키는 경우에만 성공할 것이다, 당신은 변환 후 결과를 확인해야하므로, 그렇지 않으면 널 포인터를 반환합니다

b* p = dynamic_cast<b*>(ptr); 
if (p != nullptr) 
{ 
    // It is safe to dereference p 
    p->foo(); 
} 

을 당신을 보장 할 수있는 경우 ptr이 가리키는 개체 유형은 b이지만이 경우 (가상 상속이 관련되어 있지 않으므로) static_cast<>을 사용할 수도 있습니다.이 경우 컴파일 시간에 수행되기 때문에 오버 헤드가 적습니다. GCC와 연타에

b* p = static_cast<b*>(ptr); 
// You are assuming ptr points to an instance of b. If your assumption is 
// correct, dereferencing p is safe 
p->foo(); 
3

당신은 상속 계층 구조를 내 보내야 할 것입니다. 귀하의 케이스는 적절한 유형으로 dynamic_cast을 사용하기 위해 맞춤형으로 제작되었으므로 실제로 캐스팅하려는 객체가 예상되는 유형 인 경우 유형 안전 방식으로 체크인 할 수 있습니다.

+0

dynamic_cast에 대해 생각하지 않았습니다. 유형 안전성 때문에 문제를 해결해야합니다. – user1873947

1

auto 타입 추론, 심지어 더 좋은

를 사용하여, 당신은 또한 C++ (11)을 다음과 같은 문법 설탕을

if (Base* x = dynamic_cast<Base*>(x)) { 
    // do something with \c x now that we know its defined  
} 

를 사용에서 수 (및 Visual Studio에서 내 생각)

if (auto x = dynamic_cast<Base*>(x)) { 
    // do something with \c x now that we know its defined  
} 

그리고 마지막으로 우리가 할 수 제한하려면 읽기 전용 액세스

if (const auto x = dynamic_cast<Base*>(x)) { 
    // read something from \c x now that we know its defined  
} 

x의 범위를 if 절 내부로 제한하며, 여러 개의 연속적인 dynamic_cast를 수행 한 후에 서로 ifelse if '을 사용하면 더 편리 할 수 ​​있습니다.

관련 문제