Инициализировать конструктор копирования производного класса из std :: string - PullRequest
0 голосов
/ 25 марта 2020

У меня проблема, когда я получаю класс String из std :: string и проверяю его.

Вот класс String:

namespace Types
{

class String : public std::string
{
public:
    String();

    /*!
     * @fn String(const String &other);
     * @brief Copy contructor
     * @param other
     */
    String(const String &other)
        : std::string(other) {}
    String(const char* format_string, ...);

    virtual ~String();
};

} /* namespace Types */

А вот тестовый класс :

class String_test : public CppUnit::TestFixture
{
    CPPUNIT_TEST_SUITE(String_test);
    CPPUNIT_TEST(testCopyConstructor);
    CPPUNIT_TEST_SUITE_END();

public:
    void setUp(void)
    {
        mTestObj = new Types::String();
    }
    void tearDown(void)
    {
        delete mTestObj;
    }

protected:
    void testCopyConstructor(void)
    {
        *mTestObj = "toto";
        std::cout << *mTestObj << std::endl;
        Types::String new_string((const Types::String&)mTestObj);
        CPPUNIT_ASSERT(true == true);
    }
private:
    Types::String *mTestObj;
};

Компиляция в порядке, но когда программа работает, у меня появляется эта ошибка:

##Failure Location unknown## : Error
Test name: String_test::testCopyConstructor
uncaught exception of type std::exception (or derived).
- basic_string::_M_construct null not valid

Я искал документацию о конструкторе копирования и производном классе, кажется, что это хорошо в коде. Я не понимаю, в чем проблема.

У кого-нибудь есть идеи?

Спасибо

1 Ответ

1 голос
/ 25 марта 2020

mTestObj является указателем, поэтому

(const Types::String&)mTestObj

нельзя интерпретировать как static_cast<const Types::String&>(mTestObj), потому что нет конструктора Types::String, который принимает Types::String*.

Таким образом, он будет интерпретирован как

 reinterpret_cast<const Types::String&>(mTestObj)

, который имеет то же значение, что и

 *reinterpret_cast<const Types::String*>(&mTestObj)

, поскольку по адресу mTestObj (указатель) нет объекта Types::String, доступ к результату этого приведения, как будто есть причины, вызывает неопределенное поведение. Это происходит в конструкторе копирования std::string. В качестве альтернативы, результат приведения может быть уже не указан, если есть несоответствие выравнивания для Types::String.

Не используйте приведение в стиле C, так как вы можете видеть, что они очень опасны.

Вы получаете ссылку из указателя, используя *, и вы можете получить ссылку const, позвонив по номеру std::as_const:

Types::String new_string(std::as_const(*mTestObj));

, хотя я не уверен, зачем вам нужен const во-первых, так что, вероятно, вы действительно хотите просто

Types::String new_string(*mTestObj);
...