#cpp #указатели #конструктор #преобразование
Насколько мне известно, результат выполнения new нужно присваивать указателю, т.е.: T t = new T(); //должна быть ошибка. Несоответствие типов т.к. new возвращает указатель T *t = new T(); // Правильный вариант Однако, необъяснимым для меня образом, следующий код делает первый вариант возможным. Причем только для одного конечного класса C1. Если попытаться сделать подобное с другим C2, появляется ошибка. Причем если упростить конструктор (убрать список инициализации и аргументы), то все будет работать по-обычному. #includeclass A { private: int id; static int instrumentsCount; static int lastId; public: A(); virtual ~A() = 0; }; class B:public A { private: int field1; public: B(int arg):A(),field1(arg) {std::cout<<"B\n";} }; class C1:public B { private: const bool field2; public: C1(bool o = true):B(170),field2(o){std::cout<<"C1\n";} ~C1(); }; class C2:public B { private: const int field3; public: C2(int d = 20):B(120),field3(d){std::cout<<"C2\n";} ~C2(); }; int A::instrumentsCount = 0; int A::lastId = 0; A::A() { this->id = A::lastId++; A::instrumentsCount++; std::cout<<"A "< id<<" created\n"; } A::~A() { std::cout<<"A "< id<<" destroyed\n"; A::instrumentsCount--; } C1::~C1(){} C2::~C2(){} int main(int argc, char *argv[]) { C1 c1 = new C1(true); C2 *c2 = new C2(10); return 0; } Как результат выводится следующее: A 0 created B C1 A 1 created B C1 A 2 created B C2 A 1 destroyed Что в принципе логично, но почему конструктор базового класса A вызывается при создании C1 два раза? Прошу открыть мне глаза на мои ошибки( Использую QT Creator 5.9
Ответы
Ответ 1
Имеется фундаментальный тип, для которого вы можете написать выражение T t = new T(); Таким типом является фундаментальный тип bool. bool b = new bool(); Если инициализатор отличен от нуля, то переменная получает значение true , в противном случае значение false. Из стандарта C++ (4.14 Boolean conversions) 1 A prvalue of arithmetic, unscoped enumeration, pointer, or pointer to member type can be converted to a prvalue of type bool. A zero value, null pointer value, or null member pointer value is converted to false; any other value is converted to true. For direct-initialization (8.6), a prvalue of type std::nullptr_t can be converted to a prvalue of type bool; the resulting value is false. Однако такой код ведет к утечке памяти, так как значение указателя на выделенную память теряется. В примере кода из вашего вопроса в классе C1 имеется конструктор преобразования C1(bool o = true):B(170),field2(o){std::cout<<"C1\n";} Параметр этого класса имеет тип bool, а переданный в качестве аргумента указатель может неявно быть преобразован в тип bool.Ответ 2
Да все не просто просто, а очень просто: C1 c1 = new C1(true); Итак, создается новый C1, указатель на который используется как инициализатор для конструирования c1. Есть конструктор C1(bool), который и использован. Имеем - созданный в динамической памяти C1, потерянный (утечка памяти), так как ненулевое значение указателя просто неявно преобразовано в bool для вызова второго конструктора - конструктора, который создает c1... Что логично - вы же создаете два объекта C1.Ответ 3
Моё дополнение не совсем по теме, но может быть кому-то полезно. Результат, возвращённый оператором new (или функцией malloc) можно присвоить целому числу, но нужно использовать приведение типов: uint32_t a = (uint32_t)malloc(5); Тогда в переменную a попадёт адрес участка памяти, выраженный целым числом. В рядовых программах так делать не рекомендуется, но если вы работаете напрямую с железом, это может быть полезно. Например, это число можно будет записать в регистр контроллера DMA.
Комментариев нет:
Отправить комментарий