Я новичок в C ++. У меня есть некоторые сомнения относительно множественных ошибок определений в C ++.
Допустим, у меня есть 3 файла в программе. Один заголовочный файл и 2 файла .cpp. Я включил заголовочный файл в оба файла .cpp.
Можем ли мы решить эту проблему с помощью extern
в заголовочном файле и определяя класс только в одном из файлов? Если мы можем решить проблему с помощью этого метода, нужно ли включать .cpp (с определением класса) в другой файл .cpp (без определения класса)?
Я объявил и определил класс в заголовочном файле. Является ли этот случай таким же, как указано выше (упоминается в 1)?
Я объявил класс в заголовочном файле, и я определил класс в каждом из файлов .cpp, но определения (тела функций) отличаются. Так будет ли этот тип реализации вызывать ошибку нескольких определений? Если так, как мы можем решить эту проблему, когда тела функций отличаются в файлах .cpp?
1) Вы решаете это путем «определения класса» только в одном файле cpp. Почему вы хотите определить его в двух файлах?
2) Не определяйте вещи в заголовочных файлах, только объявляйте их. Есть исключения из этого правила, например встроенные функции. Также сами классы могут быть определены более одного раза (под этим я подразумеваю объявление методов и данных-членов класса, т.е. class XYZ { ... };
) но каждое определение должно быть идентичным. Самый простой способ добиться этого — определить класс один раз в заголовочном файле. Тогда каждое определение, полученное в результате включения этого заголовочного файла в нескольких местах, обязательно будет идентичным.
3) Этот еще более глупый, одно дело определить что-то дважды, но определять это дважды и по-разному каждый раз имеет еще меньше смысла.
Я думаю, проблема в том, почему вы думаете, что иногда может быть необходимо определить вещи более одного раза. Не делай этого.
Вы также должны прояснить, что вы подразумеваете под «определением класса». Я понял это как определение методов и статических членов класса. Но если вы имеете в виду что-то еще, это может стать источником путаницы. Как обычно, лучший способ избежать путаницы в терминологии — это опубликовать некоторый код.
Чтобы ответить на все эти вопросы, вам нужно только взглянуть на назначение объявлений и определений.
Объявления класса просто утверждают, что класс существует и в каком контексте. Для класса простое предварительное объявление (например, class Banana;
) позволяет использовать указатели или ссылки на этот класс, но это все.
Определения точно определяют, что это за класс. То есть, какие члены он имеет и из каких базовых классов он получен. Это необходимо, когда вы получаете доступ к членам класса, или вам необходимо знать размер его экземпляров. Это означает, что определение класса должно быть помещено в заголовочный файл, чтобы его можно было включить во все файлы, которые используют этот класс. Это нормально, потому что стандарт говорит, что класс может быть определен в нескольких единицах перевода, если все определения идентичны.
Определение класса обычно выглядит примерно так:
class Banana
{
public:
Banana(){}
void eat();
private:
//....
};
Тем не менее, обратите внимание, что это определение класса означает только определение самого класса, а не не встроенных функций-членов. Такие как void eat()
в приведенном выше примере. Они должны быть определены в файле .cpp, потому что они не могут быть определены в нескольких единицах перевода.
Итак, вкратце:
1) В вашем проекте не может быть двух определений одного и того же класса. И я понятия не имею, как вы планируете его использовать. Если вы хотите создавать экземпляры одного класса с другим поведением, используйте виртуальную функцию, например:
class A {
public:
virtual int foo() = 0;
}
class B : public A {
public:
virtual int foo() { return 1; }
}
class C : public A {
public:
virtual int foo() { return 2; }
}
2) Вы можете определить класс в файле заголовка (в стиле java), но это не лучшая идея, потому что компилятор будет использовать больше ресурсов для создания других файлов, включая этот заголовок. Позвольте компилятору работать быстро — определяйте классы в файлах .cpp.
3) См. Стр.1
Нет проблем с определением класса в нескольких местах. Это именно то, что происходит, когда вы помещаете определение в заголовок и #include
этот заголовок в более чем одном исходном файле. Однако обратите внимание, что определение класса означает написание того, что содержит класс, а не определение его членов. Это определение класса:
class C {
void f(); // member function declaration
void g() { } // member function declaration with inline definition
int i; // member declaration
static int j; // member declaration
};
как и большинство вещей, вы не можете определить его более одного раза в одном исходном файле. Однако он может отображаться в любом количестве исходных файлов при условии, что он везде одинаков.
Это определение класса объявляет два члена, которые должны быть определены где-то, обычно так:
void C::f() {
std::cout << "In C::f\n";
}
int C::j = 3;
Эти определения могут появляться только один раз во всей программе; обычно каждый определяется один раз в исходном файле.