В последнее время у меня возникли трудности с конструкторами, и разные попытки от других вопросов и руководств всегда имеют некоторую форму 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
Поэтому в основном я спрашиваю:
main()
?EDIT: код был использован для всех, кто слишком одержим, если код "действителен по синтаксису" вместо фактического ответа на вопрос.
EDIT 2: Поскольку SEGFAULT не создаются из формата конструктора, я спрашиваю, можно ли получить SEGFAULT, если переменная экземпляра слишком велика по размеру? Я в основном спрашиваю об этом, потому что недавно я изменил элемент класса на указатель вместо объекта, и он работал нормально.
когда вы убираете класс вроде:
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. это происходит, когда вы получаете доступ к области, которой у вас нет.
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)
{};
};
Простой пример работы конструктора по умолчанию:
class base
{
int i;
public:
base()
{
i = 10;
cout << "in the constructor" << endl;
}
};
int main()
{
base a;// here is the point of doubt
getch();
}
1: Когда вызываются конструкторы по умолчанию?
в момент объявления объекта
2: Когда используются конструкторы, они также ссылаются на их конструкторы-члены?
да
3: Каким будет правильный способ объявить этих членов как в классах, так и в main()?
только то, что вы сделали
4: Каков правильный способ создания конструктора?
как можно больше, используйте список инициализации:
struct Coord3{
Coord3() : x( 0 ), y( 0 ), z( 0 ) { /* c'tor body empty */ }
float x, y, z;
};