2011-04-14 5 views
0

다음 코드 샘플이 있습니다. 하나의 기본 클래스와 각 고유 함수가있는 두 개의 파생 클래스 (function1 및 function2). function1과 function2 둘 다 기본 클래스에서 가상입니다. 이 클래스들은 이미 구현되어 있으므로 변경할 수는 없습니다.런타임에 가상 함수가없는 기본 클래스 메서드에서 파생 클래스 메서드에 액세스

#include <iostream>  
class Base 
{ 
public: 
    Base(){} 
    Base(int val) : m_base(val){} 
    virtual ~Base(){} 
    //base class methods 
private: 
    int m_base; 
}; 

class Derived1 : public Base 
{ 
public: 
    Derived1(int val) : m_derived1(val){} 
    ~Derived1(){} 
    void print1(){std::cout << "Using Derived 1 class method" << std::endl;}; 
private: 
    int m_derived1; 
}; 

class Derived2 : public Base 
{ 
public: 
    Derived2(int val) : m_derived2(val){} 
    ~Derived2(){} 
    void print2(){std::cout << "Using Derived 2 class method" << std::endl;}; 
private: 
    int m_derived2; 
}; 

지금 다음을 달성하려고합니다. 사용할 클래스를 파생 한 런타임을 결정하고 싶습니다. 또한 객체 b만을 사용하여 기본 클래스 메소드에서 호출하려고합니다. 그렇지 않으면 런타임에 입력 할 수있는 모든 옵션에 대해 프로그램을 다시 작성해야합니다 (실제로 선택할 수있는 클래스가 상당히 있습니다).

int main() 
{ 
    int option; 
    std::cin >> option; 

Base* b = new Base(5); 

Derived1* d1 = new Derived1(5); 
Derived2* d2 = new Derived2(5); 

d1->print1(); //obviously this works 
d2->print2(); //obviously this works 

//In reality I thus have a function in d1 and d2 which is not present in b 
//I have to decide on runtime which class I need to use 

if(option == 1) 
{ 
    b = d1; 
} 
else if(option == 2) 
{ 
    b = d2; 
} 

/* 
Rest of program ... 
    b->invokeMethod; 
    // ... // 
    b->invokeMoreMethods; 
*/ 

//Call derived functions on base object 

//b->print1(); //fails obviously 
if(option == 1) 
{ 
    dynamic_cast<Derived1*>(b)->print1(); //will work if option == 1 is specified (*) 
} 
if(option == 2) 
{ 
    dynamic_cast<Derived2*>(b)->print2(); //will work if option == 2 is specified (*) 
} 

return 0; 
} 

는 (선택 == 1)가없는 경우 (*) 코드 라인을 위해 가능하다면 (옵션 == 2) 루프? 구현되지 않았기 때문에 가상 기능을 사용할 수 없습니다 ...이 문제에 대한보다 우아한 해결책이 있습니까?

+1

'b'로 재 지정하면 메모리가 누출됩니다. –

+0

'Base :: m_base'가 생성자에서 초기화되지 않았습니다. 또한'Derived1 :: print1'과'Derived2 :: print2'는 기술적으로'const' 일 수 있습니다. –

답변

1

잠재적으로 포인터로 초기화되는 래퍼를 작성할 수 있으며 하루 종 료시 동적 디스패치를 ​​내부적으로 처리하지만 잠재적 인 문제는 아닙니다. 세 가지 유형을 수정할 수 있다면, 그것이 무엇을 목표로해야하는지, 다른 모든 것은 단지 불쾌한 해킹 일뿐입니다.

표준으로 ::/부스트 : : 함수를 해킹 :이 더러운 트릭입니다, 그것은 아주 쉽게 유지하기 어려워 질 것

int main() { 
    Base * b = 0;     // You were leaking a Base object here 
    boost::function< void() > f; 
    ... 
    if (option == 1) { 
     Derived1 d1 = new Derived1; // Only instantiate the object you will use 
     b = d1; 
     f = boost::bind(&Derived1::print1, d1); 
    } else if (option == 2) { 
     Derived2 d2 = new Derived2; 
     b = d2; 
     f = boost::bind(&Derived2::print2, d2); 
    } 
    ... 
    f(); // will call either d1->print1(), or d2->print2() 
    ... 
    delete b;      // should really use a smart pointer but I left 
            // the raw pointer to minimize changes 
} 

참고.

+0

David Rodriguez에게 감사 드려요. 어쨌든 나는 지금까지 더 우아한 해결책을 찾지 못했습니다. 친애하는 – user708414

관련 문제