Как правильно вызывать конструкторы по умолчанию?

0

В последнее время у меня возникли трудности с конструкторами, и разные попытки от других вопросов и руководств всегда имеют некоторую форму segfault, которая ждет меня во время выполнения (составление 80% времени, затраченного на программирование).

В следующем примере показана основная идея того, что я пытаюсь выполнить:

struct Coord3{
    float x, y, z;
    Coord3() {x=0;y=0;z=0;};///Is this Correct?
};

struct Stat{
    int Str,Dex,Int;
    Stat(){Str=0;Dex=0;Int=0;};
};

struct Item{
    Stat myStats;
    Item(){...};
};

class SimpleChar{
    public: ///to keep things simple for now
    Coord3 pos;
    Stat myStats;
    int level;
    float health;
    Item inventory[20];

    SimpleChar(){
    level=0;
    health=100;
    }///What happens with 'pos', 'inventory' and 'myStats' in this class constructor?
};

int main(){
    SimpleChar myChar;
    if(myChar.inventory[0].get()!=NULL){...}///this caused the most recent SEGFAULT as mentioned below. Why wouldn't this work?
}

В этом примере у меня есть куча более простых структур (похожих на Coord3 и Stat). Эти структуры находятся на базовом уровне моего "движка" и используются соответственно для создания структур более высокого уровня, затем они используются для создания структур самого высокого уровня (таких как Item, относящихся к SimpleChar и SimpleChar имеющих общую статистику персонажей RPG, например инвентарь и статистика). Ошибки, которые я получаю, настолько различны в зависимости от ситуации, что было сложно отслеживать их все, но самым интересным был SEGFAULT:

if(itemSet.inventory[a].get()!=NULL);///Note: this is originally a shared_ptr AND was in a struct known as 'ItemSet', which held all item information

Поэтому в основном я спрашиваю:

  1. Когда вызываются конструкторы по умолчанию?
  2. Когда используются конструкторы, они также вызывают их конструкторы-члены?
  3. Каким будет правильный способ объявить этих членов как в классах, так и в main()?
  4. Каков правильный способ создания конструктора?

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

EDIT 2: Поскольку SEGFAULT не создаются из формата конструктора, я спрашиваю, можно ли получить SEGFAULT, если переменная экземпляра слишком велика по размеру? Я в основном спрашиваю об этом, потому что недавно я изменил элемент класса на указатель вместо объекта, и он работал нормально.

  • 0
    Примечание о точках с запятой: я знаю, что некоторые из них размещены неправильно, если кто-то называет это частью проблемы :)
  • 0
    Конструкторы не связаны с вашим SEGFAULT. SEGFAULT обращается к памяти, которая не была выделена.
Показать ещё 5 комментариев
Теги:
struct
constructor
segmentation-fault
member

4 ответа

2
Лучший ответ

когда вы убираете класс вроде:

class foo{
    public:
    foo(){} // this is default constructor
};

Но если вы пишете:

class foo{};

Компилятор предоставит вам конструктор по умолчанию. Когда вы пишете:

class SimpleChar{
    Coord3 pos;   // default constructor of Coord3 will be called, 
                  //if you need somrthing else do that in SimpleChar constructor;
    Stat myStats; // same
    int level;
    float health;
    Item inventory[20];    // an array will be created that can hold 20 item,
                           // constructor (default) will be called 20 times


};

Inside main(), если вы хотите инициализировать объект со стандартным конструктором:

className instanceName; 

достаточно.

Когда вы пишете:

SimpleChar myChar;

Вызывается следующий конструктор:

SimpleChar(){
    level=0;
    health=100;
    };

Дополнительная точка ; является мандатом после определения класса или структуры, отсутствующего в item{} структуры item{}

И спецификатор доступа по умолчанию struct является общедоступным, но в классе он является частным, что означает, что вы не можете создать объект в main с конструктором по умолчанию.

Изменение: " если переменная экземпляра слишком велика по размеру ", вы можете получить std::bad_alloc если она динамически распределяется во время выполнения, но обычно не является segfault. это происходит, когда вы получаете доступ к области, которой у вас нет.

  • 0
    Хорошо, теперь я понимаю. Это означает, что способ, которым я реализовал их в реальном коде, является правильным. Также, как было сказано ранее: я знаю о неуместных и пропущенных точках с запятой, это был довольно небрежный пример. :)
  • 0
    Только упомянутый вами код не может вызвать ошибку сегментации. Поэтому я хотел ответить на ваши 5 вопросов, связанных с конструктором. причина вашего segfault в другом месте, а не в упомянутом вами коде ed.
Показать ещё 4 комментария
1

1: Когда вызываются конструкторы по умолчанию?

Конструкторы по умолчанию вызывают, когда:

  • Вы создаете объект без параметров

    MyClass * myclass= new MyClass(); //<- это вы вызываете его.

  • Когда вы наследуете от класса и не указываете конструктор в списке инициализации для этого базового класса.

    class MyClass: public BaseClass {MyClass() {}};

    MyClass * myclass= new MyClass(); //<- это вызовет конструктор по умолчанию для "MyClass" и "BaseClass".

  • Когда вы помещаете объект в любой стек и не указываете конструктор.

    void methodA() {MyClass myClass; //<-- this will invoke the default constructor for "MyClass" }//<- это вызовет конструктор по умолчанию для "MyClass"}

    То же самое происходит, если вы объявляете объект как член класса в его стеке.

    class MyClass {MyClass() {}

    DifferentClass m_member;
    

    };

Если вы не укажете другой конструктор для m_member в списке инициализации MyClass, его конструктор по умолчанию будет использоваться.

2: Когда используются конструкторы, они также ссылаются на конструкторы своего члена?

Пока они находятся в стеке, а не в куче, и вы не укажете иначе в списке инициализации класса. Да.

3: Каким будет правильный способ объявить этих членов как в классах, так и в main()?

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

MyClass myClass; //<- this is fine.

4: Каков правильный способ создания конструктора?

Хорошей практикой является ВСЕГДА инициализировать своих членов в списке инициализации, например:

struct Stat
{
    int Str,Dex,Int;

    Stat(): Str(0), Dex(0), Int(0)
    {};
};
0

Простой пример работы конструктора по умолчанию:

class base 
{
    int i;
public:

    base()
    {
        i = 10;
        cout << "in the constructor" << endl;
    }
};


int main()
{

    base a;// here is the point of doubt
    getch();
}
0

1: Когда вызываются конструкторы по умолчанию?

в момент объявления объекта

2: Когда используются конструкторы, они также ссылаются на их конструкторы-члены?

да

3: Каким будет правильный способ объявить этих членов как в классах, так и в main()?

только то, что вы сделали

4: Каков правильный способ создания конструктора?

как можно больше, используйте список инициализации:

struct Coord3{
    Coord3() : x( 0 ), y( 0 ), z( 0 ) { /* c'tor body empty */ }

    float x, y, z;    
};

Ещё вопросы

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