#c #class #function
#c #класс #функция
Вопрос:
Я изучаю c . Я написал небольшую программу, которая должна вычислить энергию системы из N частиц. До сих пор у меня есть три небольших файла:
data.h:
class Particle {
public:
double mass;
double charge;
double posx,posy,posz;
};
Particle part[2];
main.cpp:
#include <iostream>
#include "data.h"
using namespace std;
double energy(Particle part );
int main ()
{
double sd;
part[0].mass = 10.0;
part[4].mass = 90.0;
cout << part[0].mass << "n";
cout << part[4].mass << "n";
sd = energy(part);
cout << "sd" << sd << "n" ;
return 0;
}
energy.cpp:
#include <iostream>
using namespace std;
double energy(Particle part)
{
cout << part[0].mass << "n";
double dummy;
dummy = 2.0;
return (dummy);
}
У меня есть два вопроса:
1) Я хочу сделать видимой частицу класса в функции «энергия». Другими словами, я хочу использовать переменные функции класса (со значениями, указанными в «main») в энергетической функции. Я пробовал, как вы видите, energy (часть частиц), но, похоже, Particle не определена в этой области.
2) Как вы видите в «data.h», я объявил «часть» как массив с двумя элементами. Однако в «main» я могу использовать более двух членов, например part [3], part [4] … Почему я мог бы использовать больше членов, чем те, которые я объявил?
Я компилирую с помощью теста g -o energy.cpp main.cpp
Спасибо.
Комментарии:
1.
#include
заголовок. Для второго бита вы получите нарушения доступа, если вы выйдете за пределы диапазона массива.
Ответ №1:
1) Я хочу сделать видимой частицу класса в функции «энергия». Другими словами, я хочу использовать переменные функции класса (со значениями, указанными в «main») в энергетической функции. Я пробовал, как вы видите, energy (часть частиц), но, похоже, Particle не определена в этой области.
Если я вас правильно понял.. Вы хотите иметь
Particle part[2];
чтобы иметь возможность использовать в main.cpp и в energy.cpp ?
Если да.. измените это на:
extern Particle part[2];
и в energy.cpp добавьте это:
#include "data.h"
Particle part[2];
и вы сможете использовать
double energy()
{
//main.cpp will have same part
cout << part[0].mass << "n";
double dummy;
dummy = 2.0;
return (dummy);
}
2) Как вы видите в «data.h», я объявил «часть» как массив с двумя элементами. Однако в «main» я могу использовать более двух членов, например part [3], part [4] … Почему я мог бы использовать больше членов, чем те, которые я объявил?
Потому что это C / C ? нет проверки диапазона. Вы можете делать все, что захотите. Но если вы это сделаете, результат будет неожиданным.
Комментарии:
1. Мне нужно сделать видимой структуру «Particle» в другом файле с именем initial.cpp . Я скопировал строки: #включить «data.h» «Часть частиц [2];» в initial.cpp но компилятор говорит несколько определений части. Если я помещу эти две строки либо energy.cpp или initial.cpp программа работает нормально. Но почему мне не нужно объявлять «Particle part [2]» в обоих файлах?
2. вы только
#include "data.h"
!Particle part[2];
вам нужно записать только один раз, а не в несколько.cpp
файлов. Почему вам не нужно его объявлять? Мы устанавливаем его какextern
в заголовке. Мы устанавливаем переменную «один раз» в cpp-файле. Все остальные файлы, которые будут включать заголовок, будут «совместно использовать» память переменной. Обычно вы просто создаете adata.h
сextern Particle part[2];
и adata.cpp
, который будет иметь#include "data.h"
иParticle part[2];
. Тогда все остальные файлыmain.cpp
иenergie.cpp
будут просто#include "data.h"
. Обаcpp
файла смогут получить доступ кParticle part[2]
Ответ №2:
1) Я хочу сделать видимой частицу класса в функции «энергия».
Вы должны #include "data.h"
в файле energy.cpp
.
2) Как вы видите в «data.h», я объявил «часть» как массив с двумя элементами.
Вероятно, вам не следовало этого делать по двум причинам:
-
Позже вы узнаете, как избегать объявления глобальных объектов. Это законно (и часто правильно), но пока вы не научитесь, вы, вероятно, захотите объявить его как локальную переменную в
main
. -
Вы не должны объявлять глобальные объекты в файлах заголовков, поскольку они будут объявлены в каждой единице перевода, которая включает файл заголовка.
Однако в «main» я могу использовать более двух членов, например part [3], part [4] … Почему я мог бы использовать больше членов, чем те, которые я объявил?
Индексируя за пределами конца массива, вы вызываете «неопределенное поведение». Система может делать практически все (например, сбой, отправить Биллу Гейтсу электронное письмо, начать глобальную термоядерную войну и т. Д.). Среди бесконечного разнообразия вещей, включенных в «неопределенное поведение», является самым запутанным из всех — кажется, работает. Это то, что произошло в вашем случае. Вы не должны рассчитывать на то, что он продолжит работать.
Ответ №3:
С классом можно делать все, что угодно …
struct Vector3
{
double m_x, m_y, m_z;
};
class Particle
{
public:
double ComputeEnergy() { // return answer }
double GetMass() const { return m_mass; }
double GetCharge() const { return m_charge; }
const Vector3amp; GetPos() const { return m_pos; }
void SetMass(double mass) { m_mass = mass; }
void SetCharge(double charge) { m_charge = charge; }
void SetPos(const Vector3amp; pos) { m_pos = pos; }
void SetPos(double x, double y, double z)
{
m_pos.m_x = x;
m_pos.m_y = y;
m_pos.m_z = z;
}
private:
double m_mass;
double m_charge;
Vector3 m_pos;
};
Ответ №4:
Вам необходимо #include "data.h"
в energy.cpp . Включения обрабатываются только для каждого файла, поэтому energy.cpp не могу видеть заголовок без этого.
РЕДАКТИРОВАТЬ: в вашей функции параметр part
выходит за рамки глобального определения part
, поэтому part
в вашей функции это не массив. Вы хотите:
cout << part.mass << "n";
Комментарии:
1. Я добавил строку включения, но получаю следующие сообщения: energy.cpp : В функции ‘двойная энергия (частица)’: energy.cpp:7:23: ошибка: нет совпадения для ‘operator[]’ в ‘part[0]’ main.cpp : В функции ‘int main()’:main.cpp:15:18: ошибка: запрошено преобразование из ‘Particle *’ в нескалярный тип ‘Particle’
2. @armando заменить
double energy(Particle part)
наdouble energy(Particle* part)
in main.cpp amp; energy.cpp
Ответ №5:
1> Включить «data.h» в energy.cpp
2> Массив C очень примитивен, у него нет никакой проверки привязки, поэтому вы смогли получить доступ к части [4].Но нет никакой гарантии, что это будет работать каждый раз.Большую часть времени программа может аварийно завершать работу во время выполнения, жалуясь на повреждение памяти.
Ответ №6:
Чтобы ответить на первый вопрос, вы могли бы просто включить data.h в energy.cpp .
#include "data.h"
К сожалению, вы создали «часть» в глобальном пространстве, и поэтому каждый файл .cpp будет создавать его независимо. Когда он переходит к связыванию объектных файлов, он увидит, что существует несколько ссылок на «часть». Что вы можете сделать здесь, так это использовать ключевое слово «extern», а в data.h вы бы просто объявили его как внешнюю переменную. Или, потому что вы ссылаетесь только на «часть» в main.cpp , вы могли бы просто переместить туда глобальное определение, и проблема будет решена.
Теперь, когда дело доходит до того, что вы сделали в energy.cpp , вы создали отдельную переменную, также называемую «часть». Когда применяются правила определения области, это означает, что компилятор собирается использовать локальное определение вместо глобального определения. Поскольку вы передаете объект класса, а не массив классов, вы получите ошибку компилятора при ссылке на него как «часть [0].масса». Вместо этого, почему вас беспокоит значение другой частицы, а не частицы, которую вы передали? Если вам нужна масса конкретного объекта Particle, то вы должны записать его как «part.mass»
Конечно, я бы сказал, что то, что вы действительно хотите создать, — это функция-член для энергии внутри частицы. Прямо сейчас вы используете классы в виде структуры в стиле C. Это означает, что вам не хватает возможности использовать все объектно-ориентированные преимущества, которые может предложить C . Вы могли бы сделать это так
class Particle
{
protected:
double mass;
double charge;
double posx,posy,posz;
public:
void SetMass(double newMass) { mass = newMass; }
void SetCharge(double newCharge) { charge = newCharge; }
void SetX(double newX) { posX = newX; }
void SetY(double newY) { posY = newY; }
void SetZ(double newZ) { posZ = newZ; }
double GetEnergy() { return 2.0; }
};
Чтобы ответить на ваш второй вопрос, C предполагает, что вы знаете о памяти больше, чем он. В GCC (AFAIK) нет проверки границ, потому что память может быть выделена в любом месте в любое время и также освобождена. Однако, в отличие от других языков, вы должны управлять памятью самостоятельно. Существует множество оптимизаций и хитростей C , которые это позволяет (например, объявление массива нулевого размера для неизвестных размеров и назначение ему блока памяти).
Приветствия!