2009-10-09 1 views
3

У меня есть странная проблема с использованием полиморфизма. У меня есть базовый класс, который реализует статический метод. Этот метод должен быть статическим по разным причинам. Базовый класс также имеет чистый виртуальный метод run(), который реализуется всеми расширенными классами. Мне нужно иметь возможность вызвать run() из статического класса.статический метод с полиморфизмом в C++

Проблема, конечно, в том, что статический класс не имеет этого указателя. Этот метод может быть передан в параметре void *. Я пытался придумать умный способ передать в него метод run, но до сих пор ничего не работало. также попытались передать это в него. Проблема заключается в том, что я должен был бы его создать, что требует знания расширенного класса. Это побеждает всю цель полиморфизма.

Любые идеи о том, как это сделать?

+3

Я думаю, вы имеете в виду «статический метод», последний в первом абзаце? – unwind

+1

Ори, вы возражаете против передачи этого «this» статическому методу, потому что «мне нужно было бы его создать», но вы хотите вызвать виртуальный метод 'run'. Вы не можете вызвать виртуальный метод без экземпляра, поэтому вам придется создавать экземпляр класса в любом случае. Статический метод не обязательно должен знать, какой * класс был создан; он просто получает указатель базового класса, как показывает ответ Криса. –

ответ

9

Не передать его в пустоту * указатель, передать его в качестве указателя (или ссылки) на базовый класс:

class BaseClass 
{ 
public: 
    static void something(BaseClass* self) { self->foo(); } 
    virtual void foo() = 0; 
}; 
3

Почему бы не передать ссылку на объект, а не на метод, например.

static void func(BaseObject& o) 
{ 
    o.run(); 
} 
1

IMO, лучше всего, чтобы избавиться от статический метод. Найдите путь , который, и вы золотой.

5

Это обычно происходит, когда вы должны белка ваших объектов C++ через API C. Классическим примером является класс потоков.

Вот стандартная идиома для этого:

/** calls thread_func in a new thread passing it user_data as argument */ 
thrd_hdl_t c_api_thread_start(int (*thread_func)(void*), void* user_data); 

/** abstract thread base class 
* override my_thread::run to do work in another thread 
*/ 
class my_thread { 
    public: 
    my_thread() hdl_(c_api_thread_start(my_thread::thread_runner,this)) {} 
    // ... 

    private: 
    virtual int run() = 0; // we don't want this to be called from others 

    thrd_hdl_t hdl_; // whatever the C threading API uses as a thread handle 

    static int thread_runner(void* user_data) 
    { 
     my_thread* that = static_cast<my_thread*>(user_data); 
     try { 
     return that->run(); 
     } catch(...) { 
     return oh_my_an_unknown_error; 
     } 
    } 
}; 

Будет ли эта помощь?

+0

хороший сниппет, но не лучше ли использовать 'static_cast' для перевода из' void *' в другой указатель? –

+0

@Eli: Ой. Можете ли вы это сделать? Я не знал. Если вы уверены, я обязательно изменю его. (Не стесняйтесь, сделайте изменение самостоятельно.) – sbi

+0

вы, безусловно, * можете * сделать это (поскольку 'void *' статически применяется для любого указателя). Но хотите ли вы на самом деле - это хорошая практика. См. Http://stackoverflow.com/questions/310451/should-i-use-static-cast-or-reinterpret-cast-when-casting-a-void-to-whatever Поскольку это ваш ответ, я позволю вам решить :) –

Смежные вопросы