Какова лучшая подпись для клона () в C++?

Другое событие NullPointerException возникает, когда объявляется массив объектов, а затем сразу же пытается разыменовать его внутри.

String[] phrases = new String[10];
String keyPhrase = "Bird";
for(String phrase : phrases) {
    System.out.println(phrase.equals(keyPhrase));
}

Этот конкретный NPE можно избежать, если порядок сравнения отменяется ; а именно, использовать .equals для гарантированного непустого объекта.

Все элементы внутри массива инициализируются их общим начальным значением ; для любого типа массива объектов, это означает, что все элементы null.

Вы должны инициализировать элементы в массиве перед доступом или разыменованием их.

String[] phrases = new String[] {"The bird", "A bird", "My bird", "Bird"};
String keyPhrase = "Bird";
for(String phrase : phrases) {
    System.out.println(phrase.equals(keyPhrase));
}

23
задан curiousguy 3 August 2016 в 08:10
поделиться

7 ответов

Это зависит от Вашего варианта использования. Если Вы когда-нибудь думаете, что необходимо будет звонить clone на производном объекте, динамический тип которого Вы знаете (помните, смысл clone должен позволить копировать без знание динамического типа), то необходимо, вероятно, возвратить немой указатель и загрузку это в интеллектуальный указатель в коде вызова. В противном случае тогда только необходимо возвратить smart_ptr и таким образом, можно не стесняться возвращать его во всех переопределениях.

5
ответ дан coppro 29 November 2019 в 01:10
поделиться

Используйте Общественность, невиртуальную / Частный виртуальный шаблон:

class Base {
    public:
    std::auto_ptr<Base> clone () { return doClone(); }
    private:
    virtual Base* doClone() { return new (*this); }
};
class Derived : public Base {
    public:
    std::auto_ptr<Derived> clone () { return doClone(); }
    private:
    virtual Derived* doClone() { return new (*this); }
};
26
ответ дан MSalters 29 November 2019 в 01:10
поделиться

Синтаксис не вполне как хороший, но если Вы добавляете это к своему коду выше, разве это не решает все Ваши проблемы?

template <typename T>
std::auto_ptr<T> clone(T const* t)
{
    return t->clone();
}
19
ответ дан Matt Cruikshank 29 November 2019 в 01:10
поделиться

Я думаю, что функциональная семантика так ясна в этом случае, что существует мало пространства для беспорядка. Таким образом, я думаю, что можно использовать ковариантную версию (та, возвращая немой указатель на реальный тип) с легкой совестью, и вызывающие стороны будут знать, что они получают новый объект, свойство которого передается им.

7
ответ дан Gorpik 29 November 2019 в 01:10
поделиться

Tr1::shared_ptr<> может быть литым как он, был необработанный указатель.

я думаю, имеют клон (), возвращаются shared_ptr<Base>, указатель является довольно чистым решением. Можно бросить указатель на shared_ptr<Derived> посредством [1 110] tr1::static_pointer_cast<Derived> или tr1::dynamic_pointer_cast<Derived> в случае, если не возможно определить вид клонированного объекта во время компиляции.

Для обеспечения вида объекта predictible, можно использовать полиморфный бросок для shared_ptr как этот:

template <typename R, typename T>
inline std::tr1::shared_ptr<R> polymorphic_pointer_downcast(T &p)
{
    assert( std::tr1::dynamic_pointer_cast<R>(p) );
    return std::tr1::static_pointer_cast<R>(p);
}

издержки, добавленные утверждением, будут выброшены в версии выпуска.

2
ответ дан Nicola Bonelli 29 November 2019 в 01:10
поделиться

Это - одна причина использовать boost::intrusive_ptr вместо shared_ptr или auto/unique_ptr. Необработанный указатель содержит подсчет ссылок и может использоваться больше беспрепятственно в таких ситуациях.

1
ответ дан ididak 29 November 2019 в 01:10
поделиться

У Вас могло быть два метода, виртуальный клон (), который возвращает обертку интеллектуального указателя вокруг базового типа и невиртуальный clone2 (), который возвращает корректный тип интеллектуального указателя.

clone2 был бы, очевидно, реализован с точки зрения клона и инкапсулировал бы бросок.

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

Другая опция состояла бы в том, чтобы создать шаблонную версию клона, который принимает тип, который Вы ожидаете, но это добавляет больше нагрузки на вызывающей стороне.

0
ответ дан Rob Walker 29 November 2019 в 01:10
поделиться
Другие вопросы по тегам:

Похожие вопросы: