Вызов виртуальной функции объекта в памяти

0

Я пытаюсь создать встроенный конструктор для класса, который имеет виртуальную функцию. Для общей цели функция должна быть виртуальной, потому что Shape::print будет вызываться другим классом, не зная, какой тип (точный тип) формы, на которую он обращается.

Я вижу, что это должна быть какая-то проблема, связанная с памятью. Как я могу вызвать эту функцию при использовании моего объекта класса, но не как указателя? Или я пропустил что-то еще?

#include <stdio.h>
#include <stdlib.h>

using namespace std;

class Shape {
public:
    virtual void print(){};
};

class Circle : Shape {
private:
    int r;
public:
    Circle(int radius){
        this->r = radius;
    }

    // My "inline-constructor"
    static Circle* make(int radius){
        Circle* circ = (Circle*) malloc(sizeof(Circle));
        circ->r = radius;
        return circ;
    };

    virtual void print(){
        printf("%u", this->r);
    };
};

int main(){
    Circle circObj(5);
    circObj.print(); // Works fine    
    Circle* circPtr = Circle::make(10);
    circPtr->print(); // Crashes    
    return 0;
 }

Спасибо заранее, любая помощь будет оценена.

  • 1
    Лучшим названием для «встроенного конструктора» будет «фабричная функция»
  • 0
    Если бы я назвал что-то вроде (new Circle(10))->print(); разве объект не будет удален из памяти впоследствии?
Показать ещё 1 комментарий
Теги:
class
pointers
virtual

3 ответа

2
Лучший ответ
// My "inline-constructor"
static Circle* make(int radius){
    Circle* circ = (Circle*) malloc(sizeof(Circle));
    circ->r = radius;
    return circ;
};

Это не какой-то конструктор. Это просто ошибочно написанный заводский метод. Он должен состоять только из

return new Circle(radius);

что делает его настолько тривиальным, что совершенно бессмысленно.

Как я могу вызвать эту функцию при использовании моего объекта класса, но не как указателя?

Shape* shape = ....; // for example, new Circle(...)
shape->print();

Нет ракетной науки

  • 0
    Спасибо за помощь!
3

В вас "встроенный-конструктор" вы просто выделяете память, а не инициализируете ее. Например, vtable не инициализируется, что приводит к сбою, так как print является виртуальной и ее адрес ожидается в vtable.

Попробуйте Circle* circ = new Circle(radius); вместо malloc.

1

Проблема в том, что malloc просто выделяет достаточную необработанную память и возвращает ее. malloc не инициализирует созданную память. Поэтому члены вашего объекта должны быть инициализированы вручную перед использованием. Вы делаете это только для r, но не для print метода члена.

Вы должны использовать new вместо malloc. new работы в два этапа

  1. Выделите достаточно памяти с помощью оператора new (эквивалентная задача malloc)
  2. Вызов конструктора объекта для его инициализации, который фактически устанавливает значения для элемента.
  • 0
    Спасибо, собираюсь запомнить это для себя ;-)

Ещё вопросы

Сообщество Overcoder
Наверх
Меню