Ваш метод 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
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...
Вы также иногда явно используете конструктор для создания временного , Например, если у вас есть какой-то класс с конструктором:
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
использует эту технику для вызова конструктора копирования. Таким образом, ему нужно сделать только одну копию вместо создания пустого объекта и использования оператора присваивания.
Я думаю, что сообщение об ошибке для ошибки компилятора C2585 дает лучшую причину, по которой вам нужно было бы на самом деле использовать оператор разрешения области действия в конструкторе, и это соответствует ответу Чарли:
Преобразование из класса или типа структуры на основе множественного наследования. Если тип наследует один и тот же базовый класс более одного раза, функция или оператор преобразования должны использовать разрешение области (: :), чтобы указать, какие из унаследованных классов использовать в преобразовании.
Представьте, что у вас есть BaseClass, а BaseClassA и BaseClassB оба наследуют BaseClass, а затем DerivedClass наследует оба BaseClassA и BaseClassB.
Если вы выполняете преобразование или перегрузку оператора для преобразования DerivedClass в BaseClassA или BaseClassB, вам необходимо определить, какой конструктор (я думаю, что-то вроде конструктор копирования,
Я не думаю, что вы обычно используете это для конструктора, по крайней мере, не так, как вы переписываю. Однако он вам понадобится, если у вас есть два класса в разных пространствах имен. Например, чтобы указать разницу между этими двумя составными классами, Xml :: Element
и Chemistry :: Element
.
Обычно имя класса используется с оператор разрешения области для вызова функции родительского класса унаследованного класса. Таким образом, если у вас есть класс Dog, который наследует от Animal, и оба этих класса по-разному определяют функцию Eat (), может быть случай, когда вы захотите использовать версию Eat в Animal для объекта Dog с именем «someDog». Мой синтаксис C ++ немного ржавый,
Как правило, вы не вызываете конструктор напрямую. Оператор new вызывает его за вас, или подкласс вызывает конструкторы родительского класса. В C ++ гарантируется, что базовый класс будет полностью построен до запуска конструктора производного класса.
Единственный раз, когда вы вызываете конструктор напрямую, - это чрезвычайно редкий случай, когда вы управляете памятью без использования new. И даже тогда тебе не следует т сделать это. Вместо этого вы должны использовать форму размещения оператора new.
Существуют обоснованные случаи использования, когда вы хотите раскрыть конструкторы класса. Например, если вы хотите управлять памятью с помощью аллокатора арены, вам понадобится двухфазная конструкция, состоящая из аллокации и инициализации объекта.
Мой подход похож на подход многих других языков. Я просто помещаю свой код построения в хорошо известные публичные методы (Construct(), init(), что-то вроде этого) и вызываю их напрямую, когда это необходимо.
Вы можете создавать перегрузки этих методов, которые соответствуют вашим конструкторам; ваши обычные конструкторы просто вызывают их. Поместите в код большие комментарии, чтобы предупредить других, что вы делаете это, чтобы они не добавили важный код конструктора в неправильном месте.
Помните, что существует только один метод деструктора, независимо от того, какая перегрузка конструкции была использована, поэтому сделайте ваши деструкторы устойчивыми к неинициализированным членам.
Я не рекомендую пытаться писать инициализаторы, которые могут повторно инициализироваться. Трудно отличить случай, когда вы смотрите на объект, в котором просто есть мусор из-за неинициализированной памяти, от случая, когда в нем действительно хранятся реальные данные.
Самая сложная проблема возникает с классами, имеющими виртуальные методы. В этом случае компилятор обычно вставляет указатель таблицы функций vtable в качестве скрытого поля в начале класса. Вы можете вручную инициализировать этот указатель, но в этом случае вы будете зависеть от поведения компилятора, и, скорее всего, ваши коллеги будут смотреть на вас со смехом.
Placement new сломан во многих отношениях; в построении/уничтожении массивов - это один из случаев, поэтому я склонен не использовать его.