Явный конструктор копирования

Я расширил std::string, чтобы удовлетворить свои потребности в написании пользовательской функции, встроенной в строковый класс с именем CustomString.

Я определил конструкторы:

    class CustomString : public std::string {
    public:
        explicit CustomString(void);
        explicit CustomString(const std::string& str);
        explicit CustomString(const CustomString& customString);
        //assignment operator
        CustomString& operator=(const CustomString& customString);
    ... };

В третьем конструкторе (конструкторе копирования) и операторе присваивания, определение которого:

CustomString::CustomString(const CustomString& customString):
    std::string(static_cast<std::string>(customString)) 
{}
CustomString& CustomString::operator=(const CustomString& customString){
    this->assign(static_cast<std::string>(customString));
    return *this;
}

Во-первых, поскольку это «явное»; это означает, что для назначения другому объекту CustomString требуется явное приведение; он жалуется на задание.

CustomString s = CustomString("test");

Я не уверен, где именно требуется явное приведение.

Код работает нормально, если конструктор копирования не является явным, но я хотел бы знать и реализовать явное определение вместо «угадывания правильного приведения».


person abumusamq    schedule 14.07.2012    source источник


Ответы (2)


Явный конструктор копирования означает, что конструктор копирования не будет вызываться неявно, что и происходит в выражении:

CustomString s = CustomString("test");

Это выражение буквально означает: создайте временный CustomString с помощью конструктора, который принимает const char*. Неявно вызовите конструктор копирования CustomString, чтобы скопировать из этого временного файла в s.

Теперь, если бы код был правильным (т. е. если бы конструктор копирования не был явным), компилятор избегал бы создания временного и исключал бы копию, создавая s непосредственно со строковым литералом. Но компилятор все равно должен проверить, что построение может быть выполнено и там происходит сбой.

Вы можете вызвать конструктор копирования явно:

CustomString s( CustomString("test") );

Но я бы порекомендовал вам вообще избегать временных и просто создавать s с const char*:

CustomString s( "test" );

Что компилятор и сделал бы в любом случае...

person David Rodríguez - dribeas    schedule 14.07.2012
comment
О да, я полностью понимаю ваш ответ (и это правильный ответ, и я отметил его как лучший ответ), но как мне добиться, например, CustomString s = customStringObjectOnStack;? - person abumusamq; 14.07.2012
comment
@ mkhan3189 вы можете добиться CustomString s = customStringObjectOnStack тогда и только тогда, когда copy-ctor не будет явным. Второй вопрос: kDelimited — это CustomString или что-то еще? И + ваша функция является константной, поэтому c.append(static_cast‹const std::string&›(*this)) будет работать. - person ForEveR; 14.07.2012
comment
@ForEveR Да, спасибо за это. Я получил ответ сам. kDelimiter - это постоянный объект CustomString, да. c.append(static_cast<std::string>(*this)) работает для неявного объявления copy-ctor. Так что все хорошо. Эту тему можно закрыть. - person abumusamq; 14.07.2012
comment
@ mkhan3189: Вы можете достичь CustomString s = customStringObjectOnStack;, вместо неявного использования этого конструктора копирования с синтаксисом =, вы явно вызываете конструктор копирования: CustomString s( customStringObjectOnStack ); - person David Rodríguez - dribeas; 14.07.2012

Наследование от std::string небезопасно, так как std::string не имеет виртуального деструктора. Что касается вашего вопроса - ваши конструкторы копирования не должны быть явными, чтобы разрешить такое использование, как:

CustomString s = "test";

Также я понятия не имею, почему вы хотите объявить конструктор копирования явным, поскольку он не нужен. Явный конструктор копирования будет работать, только если вы объявите свой объект CustomString как:

CustomString s(CustomString("test"));
person ForEveR    schedule 14.07.2012
comment
@ildjarn: почему ленивый? Правильно (не оптимально, но правильно) решает проблему и дает решение... - person David Rodríguez - dribeas; 14.07.2012
comment
@DavidRodríguez-dribeas, когда ildjarn публиковал комментарий, ответ был короче. - person ForEveR; 14.07.2012
comment
Спасибо и хороший ответ, но это лениво, потому что я попросил это улучшить мой способ написания кода, а не просто сделать что-то. В любом случае спасибо :) - person abumusamq; 14.07.2012
comment
Пока OP только использует CustomStrings и, скажем, не пытается delete new CustomString через указатель std::string, есть ли действительно что-то небезопасное в этом производном? - person Joshua Green; 22.10.2014
comment
"Пока [...], есть ли что-нибудь небезопасное?". Если у вас нет средств для надежного и последовательного соблюдения условий с течением времени, включая код коллеги и везде, где это может быть скопировано в будущем, ответ на этот вопрос всегда будет «да». Неважно, что в [...]. - person spectras; 21.08.2020