Как создать экземпляр структуры на С++?
Проблема заключается в сообщении об ошибке "Ошибка записи о местоположении 0x00000000" сразу после инициализации переменной bk
до NULL
. Я предполагаю, что я должен заранее зарезервировать пространство памяти, чтобы назначить NULL
(что-то вроде Book bk = new Book();
), но до сих пор мне не удалось выяснить, как это сделать на С++.
Book.h
#ifndef Book_H
#define Book_H
struct _book;
typedef _book* Book;
Book CreateBook(unsigned int pageNum);
Book.cpp
#include "Book.h"
#include <iostream>
#ifndef Book_CPP
#define Book_CPP
using namespace std;
struct _book
{
int pageNum;
};
Book CreateBook( unsigned int pageNum){
Book bk = NULL;
bk->pageNum = pageNum;
return bk;
};
Ответы
Ответ 1
Вы назначаете bk в NULL, а затем пытаетесь получить доступ к его члену. То же, что и нулевой указатель в Java, и то, что вы делаете, обычно вызывает исключение NullPointerException (спасибо из комментариев). Если вы хотите создать указатель на свою структуру, вам нужно использовать оператор new:
bk = new _book;
// ...
return bk;
а затем убедитесь, что вы вызываете delete по указателю, когда закончите с ним.
Я бы посоветовал не использовать указатели здесь. В отличие от других языков, С++ позволяет создавать объекты по значению. Он также позволяет использовать ссылки и указатели, но только использовать указатели, когда вы абсолютно должны. Если вы просто хотите создать объект книги с заданным pageNum, вы должны создать конструктор, пока вы на нем:
struct _book {
int pageNum;
_book(int n) : pageNum(n) // Create an object of type _book.
{
}
};
а затем вы можете вызвать его как
_book myBook(5); // myBook.pageNum == 5
Если вы новичок в С++, пожалуйста, возьмите себе хорошую книгу. Это не только язык низкого уровня, но и не только язык ООП. Это многопартийный швейцарский армейский ножевой язык.
Ответ 2
Это то, что вам нужно:
Book CreateBook( unsigned int pageNum){
Book bk = new _book();
bk->pageNum = pageNum;
return bk;
}
ваш bk был null, и вы не можете получить доступ к pageNum, когда указатель имеет значение null.
И не забудьте вызвать delete на bk, когда вы закончите использовать его.
Ответ 3
Book.h
#ifndef Book_H
#define Book_H
// why not put the layout here?
struct Book
{
int pageNum;
};
Book CreateBook(unsigned int pageNum);
#endif
Book.cpp
#include "Book.h"
// no #define guards
// do not using namespace std;, it is a bad habit
Book CreateBook( unsigned int pageNum){
Book bk;
bk.pageNum = pageNum;
return bk;
};
Это простейшее решение. Книги являются фактическими значениями и могут быть скопированы и перемещены и т.д.
Если вам нужна непрозрачность абстрактного типа, только тогда вы должны иметь дело с указателями. Когда вы имеете дело с указателями, прятать их за typedef
- это плохая идея: указатели означают управление ресурсами, поэтому должно быть очевидно, что вы их используете.
Версия на основе указателя:
#ifndef Book_H
#define Book_H
// why not put the layout here?
struct Book;
Book* CreateBook(unsigned int pageNum);
#endif
* Book.cpp *
#include "Book.h"
// no #define guards
// do not using namespace std;, it is a bad habit
Book* CreateBook( unsigned int pageNum){
Book* bk = new Book;
bk->pageNum = pageNum;
return bk;
};
но если вы создаете материал, вы, вероятно, должны создавать интеллектуальные указатели:
#include <memory>
std::shared_ptr<Book> CreateBook( unsigned int pageNum){
std::shared_ptr<Book> bk( new Book );
bk->pageNum = pageNum;
return bk;
};
Ответ 4
В
Book bk;
bk
является указателем
Сначала выделите память для него
Book bk* = new _book();
И затем сделайте
bk->pageNum = pageNum;
Также не забудьте освободить память, используя
delete bk;
Ответ 5
Почему вы делаете типизацию? В некоторых случаях это может быть хорошей практикой по некоторым причинам.
Если вы не знали, вы также можете написать:
_book book;
Теперь книга распределяется статически в стеке вместо динамически в куче. Он автоматически уничтожается, когда переменная выходит за пределы области видимости, как int или double, и т.д.
Это полезно иногда, если вы хотите избежать накладных расходов или работы по распределению памяти для чего-то очень простого. Было странно, что я пошел на Java и должен сказать:
vec3 position = new Vec3 (0.0, 1.0, 5.0);
вместо того, чтобы просто сказать
позиция vec3 (0.0, 1.0, 5.0);
как в С++.
Ответ 6
struct Book{
int pageNum;
};
Book* createBook(int pageNum){
Book *result = new Book;
result->pageNum = pageNum;
return result;
}
int main(int argc, char** argv){
Book book;
book.pageNum = 0;
return 0;
}
или
struct Book{
int pageNum;
Book(int pageNum_ = 0)
:pageNum(pageNum_){
}
};
Book* createBook(int pageNum){
return new Book(pageNum);
}
int main(int argc, char** argv){
Book book(0);
return 0;
}
Ответ 7
но если вы не хотите создавать переменную из кучи, вы можете напрямую создать и вернуть этот путь
bk = _book{any_data_that_you_want_to_insert};
// ...
return bk;
Ответ 8
В вашем коде есть несколько ошибок.
- Вам нужно положить
#endif
в конец вашего файла заголовка.
- Вам нужно поместить точку с запятой в конце определений
struct
, class
и union
(после закрывающей скобки).
- Вы не должны использовать указатели вообще в таком простом случае.
Пример:
Book.h
#ifndef BOOK_H
#define BOOK_H
struct Book
{
int pageNum;
};
Book CreateBook(int pageNum);
#endif
Book.cpp
#include "Book.h"
Book CreateBook(int pageNum)
{
Book bk;
bk.pageNum = pageNum;
return bk;
}
В любом случае вам не нужна функция CreateBook
, но я все равно оставил ее.