2009-03-10 5 views
0

Это странный вариант. Обратите внимание, что это сокращает пример кода и упускает деструкторы сознательно).const указатель как аргумент конструктора

template <class f, class g> class Ptr; 

class RealBase 
{ 
}; 

template <class a, class b, class c = Ptr<a,b> > 
class Base : public RealBase 
{ 
public: 
    Base(){}; 
}; 

template <class d, class e> 
class Derived : public Base <d,e> 
{ 
public: 
    Derived(){}; 
    void DerivedMethod(){}; 
}; 
typedef Derived<double,double> D_Derived; 

template <class f, class g> 
class Ptr 
{ 
public: 
    Ptr(){}; 
    Ptr(Base<f,g,Ptr<f,g> >* a){in = a;}; 
    Base<f,g,Ptr<f,g> >* operator->() 
    { 
     return in; 
    }; 

    Base<f,g,Ptr<f,g> >& operator*() 
    { 
     return *in; 
    }; 
private: 
    Base<f,g,Ptr<f,g> >* in; 
}; 

Я использую класс Ptr из этого примера в векторе как указатель на класс Derived.

Как мы видим, Ptr принимает Base<>* как аргумент конструктора.

К сожалению, мне нужен конструктор, который принимает константный Base <> *, и я просто не могу это сделать:

Ptr(const Base<>* a) { in = const_cast<Base<>*>(a)}; 

Любые идеи, как я могу сделать этот класс принять const Base<>*, как это конструктор?


Edit:

Хорошо, получается, что я могу это исправить путем внесения изменений в несвязанный код, так что это немного не-проблема сейчас =] У меня ушел около дня, чтобы исправить это, хотя = [

+1

вы потерял меня в «не уныне или что-то еще». –

+0

Приношу свои извинения. В прошлый раз, когда я опубликовал код примера вырезания, какой-то парень продолжал рассказывать о том, как у меня не было виртуальных деструкторов. –

ответ

2

Я думаю, вам нужно определить отдельный класс для привязки указателей к const, так как вместо константных версий должны быть изменены не только аргументы конструктора, но и возвращаемые типы операторов. Если вы сделаете ConstPtrfriend из Ptr, это должно работать довольно красиво:

template<...> 
class ConstPtr { 
    const Base<...> *in; 
    ConstPtr(Base<...>* a) { in = a; } 
    ConstPtr(const Base<...>* a) { in = a; } 
    ConstPtr(const Ptr<...> &a) { in = a.in; } 
    ... 
}; 

Для построения оберток из сырых указателей можно добавить перегруженную функцию, более или менее, как это:

template<..., class P> 
P make_ptr(Base<...> *t); 

template<...> 
Ptr<...> make_ptr< ..., Ptr<...> >(Base<...> *t) { 
    return Ptr(t); 
} 

template<...> 
ConstPtr<...> make_ptr< ..., ConstPtr<...> >(const Base<...> *t) { 
    return ConstPtr(t) 
} 
+0

Есть ли шанс быть немного более подробным в синтаксисе друга? Это не работает, как я ожидал, и я хотел бы видеть то, что вы на самом деле имели в виду! –

+0

Мой план состоял в том, чтобы поставить «friend ConstPtr <...>;» в определении «Ptr <...>», чтобы конструктор ConstPtr получал доступ к «a.in». Я не тестировал его, хотя, возможно, есть некоторые осложнения из-за шаблонов. – sth

+0

Хорошо, вот что я сделал. Есть ли способ выбросить его в ConstPtr автоматически? Это не возможность иметь разные классы для двух опций opti –

1

В вашем классе Ptr есть указатель-указатель, не являющийся константой. Вы не сможете назначить const Base* без каких-либо небезопасных бросков. Вы хотите, чтобы? Попробуйте вместо этого:

template <class f, class g> 
class Ptr 
{ 
    public: 
    Ptr(){}; 
    Ptr(Base<f,g,Ptr<f,g> > const* a) { in = *a; } 
    Base<f,g,Ptr<f,g> >* operator->() 
    { 
     return &in; 
    }; 

    Base<f,g,Ptr<f,g> >& operator*() 
    { 
     return in; 
    }; 

private: 
    Base<f,g,Ptr<f,g> > in; 
}; 
+0

Хм. Выглядит хорошо, но если Base > имеет член типа Ptr , это создаст класс бесконечного размера. Но я не понял, что пытается сделать OP. Я не уверен, что это будет так ... –

+0

Простите, это не выполнимый вариант: я должен держать указатель на исходный объект в этом а не сам объект, чтобы делать что-то с адресами позже (это не хороший код). Полная версия это симулятор нейронной сети, так что понадобится около недели, чтобы объяснить всю ситуацию! –

1

по вашему примеру, вы должны сделать

Ptr(const Base< f,g, Ptr< f, g > >* a) 
{ 
    in = const_cast< Base<f,g,Ptr<f,g> >* > (a); 
} 

пс: Я не люблю const_cast и в подобных случаях, я стараюсь, чтобы избежать этого. Возможно, нужно выполнить две реализации Ptr для аргументов const и non const.

+0

«Недопустимое использование const_cast с типом 'Ptr ', которое не является указателем, ссылкой или типом типа указателя на данные." Я уже говорил, что это не вариант. –

+0

Я не знаю, почему вы не можете скомпилировать мой образец. Я тестировал это на моем компиляторе msvc 2005 - все в порядке. Пожалуйста, предоставьте самую подробную информацию о вашей проблеме. – bayda

+0

Я понимаю, что код СЛЕДУЕТ компилировать. Однако для совершенно неизвестных и, вероятно, невероятно сложных причин это не так, как я сказал в вопросе. Я удалю -1, но вы должны действительно прочитать вопрос перед ответом. –

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