Почему явно вызывают конструктора в C++

Ваш метод Utility.exist_request_xml возвращает nil, что неверно в выражении if, поэтому он переходит к другому, где вы не открываете файл.

Возвращает nil, потому что по умолчанию последнее вычисленное выражение является возвращаемым значением, а ваше последнее выражение - if. Точно так же возвращаемое значение if - это последнее, что оценивает , которое он оценивает, - это puts (в любой ветви). puts возвращает nil.

Вместо этого верните значение проверки существования:

def Utility.exist_request_xml filexml
  File.exist? "#{PATH_WEBSERVICES_REQUEST}/#{filexml}"
end
21
задан Keith Pinson 25 March 2013 в 17:54
поделиться

6 ответов

Most often, in a child class constructor that require some parameters :

class BaseClass
{
public:
    BaseClass( const std::string& name ) : m_name( name ) { }

    const std::string& getName() const { return m_name; }

private:

    const std::string m_name;

//...

};


class DerivedClass : public BaseClass
{
public:

    DerivedClass( const std::string& name ) : BaseClass( name ) { }

// ...
};

class TestClass : 
{
public:
    TestClass( int testValue ); //...
};

class UniqueTestClass 
     : public BaseClass
     , public TestClass
{
public:
    UniqueTestClass() 
       : BaseClass( "UniqueTest" ) 
       , TestClass( 42 )
    { }

// ...
};

... for example.

Other than that, I don't see the utility. I only did call the constructor in other code when I was too young to know what I was really doing...

14
ответ дан 29 November 2019 в 06:34
поделиться

Вы также иногда явно используете конструктор для создания временного , Например, если у вас есть какой-то класс с конструктором:

class Foo
{
    Foo(char* c, int i);
};

и функцией

void Bar(Foo foo);

, но у вас нет Foo, вы можете сделать

Bar(Foo("hello", 5));

Это похоже на приведение. Действительно, если у вас есть конструктор, который принимает только один параметр, компилятор C ++ будет использовать этот конструктор для выполнения неявных приведений.

не законно вызывать конструктор для уже существующего объекта. То есть вы не можете делать

Foo foo;
foo.Foo();  // compile error!

независимо от того, что вы делаете. Но вы можете вызвать конструктор, не выделяя память - для этого размещено размещение new .

char buffer[sizeof(Foo)];      // a bit of memory
Foo* foo = new(buffer) Foo();  // construct a Foo inside buffer

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

Например, std :: vector :: push_back использует эту технику для вызова конструктора копирования. Таким образом, ему нужно сделать только одну копию вместо создания пустого объекта и использования оператора присваивания.

но часто встречается во встроенном и структурном коде данных.

Например, std :: vector :: push_back использует эту технику для вызова конструктора копирования. Таким образом, ему нужно сделать только одну копию вместо создания пустого объекта и использования оператора присваивания.

но часто встречается во встроенном и структурном коде данных.

Например, std :: vector :: push_back использует эту технику для вызова конструктора копирования. Таким образом, ему нужно сделать только одну копию вместо создания пустого объекта и использования оператора присваивания.

44
ответ дан 29 November 2019 в 06:34
поделиться

Я думаю, что сообщение об ошибке для ошибки компилятора C2585 дает лучшую причину, по которой вам нужно было бы на самом деле использовать оператор разрешения области действия в конструкторе, и это соответствует ответу Чарли:

Преобразование из класса или типа структуры на основе множественного наследования. Если тип наследует один и тот же базовый класс более одного раза, функция или оператор преобразования должны использовать разрешение области (: :), чтобы указать, какие из унаследованных классов использовать в преобразовании.

Представьте, что у вас есть BaseClass, а BaseClassA и BaseClassB оба наследуют BaseClass, а затем DerivedClass наследует оба BaseClassA и BaseClassB.

Если вы выполняете преобразование или перегрузку оператора для преобразования DerivedClass в BaseClassA или BaseClassB, вам необходимо определить, какой конструктор (я думаю, что-то вроде конструктор копирования,

3
ответ дан 29 November 2019 в 06:34
поделиться

Я не думаю, что вы обычно используете это для конструктора, по крайней мере, не так, как вы переписываю. Однако он вам понадобится, если у вас есть два класса в разных пространствах имен. Например, чтобы указать разницу между этими двумя составными классами, Xml :: Element и Chemistry :: Element .

Обычно имя класса используется с оператор разрешения области для вызова функции родительского класса унаследованного класса. Таким образом, если у вас есть класс Dog, который наследует от Animal, и оба этих класса по-разному определяют функцию Eat (), может быть случай, когда вы захотите использовать версию Eat в Animal для объекта Dog с именем «someDog». Мой синтаксис C ++ немного ржавый,

0
ответ дан 29 November 2019 в 06:34
поделиться

Как правило, вы не вызываете конструктор напрямую. Оператор new вызывает его за вас, или подкласс вызывает конструкторы родительского класса. В C ++ гарантируется, что базовый класс будет полностью построен до запуска конструктора производного класса.

Единственный раз, когда вы вызываете конструктор напрямую, - это чрезвычайно редкий случай, когда вы управляете памятью без использования new. И даже тогда тебе не следует т сделать это. Вместо этого вы должны использовать форму размещения оператора new.

2
ответ дан 29 November 2019 в 06:34
поделиться

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

Мой подход похож на подход многих других языков. Я просто помещаю свой код построения в хорошо известные публичные методы (Construct(), init(), что-то вроде этого) и вызываю их напрямую, когда это необходимо.

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

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

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

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

Placement new сломан во многих отношениях; в построении/уничтожении массивов - это один из случаев, поэтому я склонен не использовать его.

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

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