Подтвердить что ты не робот

Что касается С++ Включить другой класс

У меня есть два файла:

File1.cpp
File2.cpp

File1 - это мой основной класс, который имеет основной метод, File2.cpp имеет вызов класса ClassTwo, и я хочу создать объект ClassTwo в файле File1.cpp

Я скомпилирую их вместе

g++ -o myfile File1.cpp File2.cpp

но когда я пытаюсь создать

//создать объект класса 2

ClassTwo ctwo;

Это не работает.

Ошибка была

ClassTwo не был объявлен в этой области.

Это мой main.cpp

#include <iostream>
#include <string>
using namespace std;

int main()
{
//here compile error - undeclare ClassTwo in scope.
ClassTwo ctwo;

//some codes
}

Вот мой File2.cpp

#include <iostream>
#include <string>

using namespace std;

class ClassTwo
{
private:
string myType;
public:
void setType(string);
string getType();
};


void ClassTwo::setType(string sType)
{
myType = sType;
}

void ClassTwo::getType(float fVal)
{
return myType;
}

Получил ответ на разделение файла File2.cpp на другой .h файл, но если я объявляю класс, как разбить его на другой файл .h, так как мне нужно поддерживать public и private переменной (private) и функции (public) и как я могу получить ClassTwo для моего File1.cpp по основному методу

4b9b3361

Ответ 1

Какова основная проблема в вашем коде?

Ваш код необходимо разделить на интерфейсы (.h) и Реализации (.cpp).
Компилятор должен видеть композицию типа, когда вы пишете что-то вроде

ClassTwo obj;

Это связано с тем, что компилятору необходимо зарезервировать достаточно памяти для объекта типа ClassTwo, чтобы сделать это, чтобы увидеть определение ClassTwo. Самый распространенный способ сделать это в С++ - это разделить ваш код на файлы заголовков и исходные файлы.
Определения классов входят в заголовочный файл, а реализация класса входит в исходные файлы. Таким образом, можно легко включать заголовочные файлы в другие исходные файлы, которые должны видеть определение класса, который создает объект.

Почему я не могу просто поместить весь код в файлы cpp и включить их в другие файлы?

Вы не можете просто поместить весь код в исходный файл и затем включить этот исходный файл в другие стандартные мандаты files.С++, чтобы вы могли объявить объект столько раз, сколько вам нужно, но вы можете определить его только один раз (Одно правило определения (ODR)). Включение исходного файла нарушит ODR, потому что копия объекта создается в каждом блоке , где файл включен.

Как решить эту конкретную проблему?

Ваш код должен быть организован следующим образом:

// File1.h

Define ClassOne 

// File2.h

#include <iostream>
#include <string>


class ClassTwo
{
private:
   string myType;
public:
   void setType(string);
   std::string getType();
}; 

//File1.cpp

#include"File1.h"

Implementation of ClassOne 

//File2.cpp

#include"File2.h"

void ClassTwo::setType(std::string sType)
{
    myType = sType;
}

void ClassTwo::getType(float fVal)
{
    return myType;
} 

//main.cpp

#include <iostream>
#include <string>
#include "file1.h"
#include "file2.h"
using namespace std;

int main()
{

    ClassOne cone;
    ClassTwo ctwo;

    //some codes
}

Есть ли альтернативные способы, а не включать файлы заголовков?

Если вашему коду нужно создавать указатели, а не фактические объекты, вы можете использовать Forward Declarations, но обратите внимание, что использование форвардных объявлений добавляет некоторые ограничения на то, как этот тип можно использовать, потому что компилятор видит этот тип как Неполный тип.

Ответ 2

С++ (и C в этом отношении) разделяет "объявление" и "реализацию" типов, функций и классов. Вы должны "объявить" классы, которые вам нужны, в заголовочном файле (.h или .hpp) и поместить соответствующую реализацию в файл .cpp. Затем, когда вы хотите использовать (доступ) к классу где-нибудь, вы # включаете соответствующий заголовочный файл.

Пример

ClassOne.hpp:

class ClassOne
{
public:
  ClassOne(); // note, no function body        
  int method(); // no body here either
private:
  int member;
};

ClassOne.cpp:

#include "ClassOne.hpp"

// implementation of constructor
ClassOne::ClassOne()
 :member(0)
{}

// implementation of "method"
int ClassOne::method()
{
  return member++;
}

main.cpp:

#include "ClassOne.hpp" // Bring the ClassOne declaration into "view" of the compiler

int main(int argc, char* argv[])
{
  ClassOne c1;
  c1.method();

  return 0;
}

Ответ 3

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

class ClassTwo;

Важно: Это работает только в некоторых случаях, см. ответ Als для получения дополнительной информации..

Ответ 4

Вещь с компиляцией двух файлов .cpp в одно и то же время, это не означает, что они "знают" об eachother. Вам нужно будет создать файл, "говорит" ваш File1.cpp, на самом деле есть функции и классы, такие как ClassTwo. Этот файл называется header-file и часто не содержит кода исполняемого. (Есть исключения, например, для встроенных функций, но сначала забывайте их) Они служат декларативной необходимости, просто для того, чтобы рассказать, какие функции доступны.

Когда у вас есть File2.cpp и включите его в свой File1.cpp, вы увидите небольшую проблему: Один и тот же код дважды: один в File1.cpp и один в нем, File2.cpp.

Поэтому вы должны создать файл заголовка, например File1.hpp или File1.h (возможны другие имена, но это просто стандарт). Он работает следующим образом:

//File1.cpp

void SomeFunc(char c) //Definition aka Implementation
{
//do some stuff
}

//File1.hpp

void SomeFunc(char c); //Declaration aka Prototype

И для чистого кода вы можете добавить следующее в начало File1.cpp:

#include "File1.hpp"

И следующий, окружающий File1.hpp код:

#ifndef FILE1.HPP_INCLUDED
#define FILE1.HPP_INCLUDED
//
//All your declarative code
//
#endif

Это делает ваш заголовочный файл более чистым, для дублирования кода.

Ответ 5

Если вы хотите преобразовать свой код в результат (исполняемый файл, библиотеку или что-то еще), есть 2 шага:
1) компилировать
2) ссылка
На первом этапе компилятор должен теперь рассказать о некоторых вещах, например, о размерах объектов, которые вы использовали, прототипе функций и, возможно, наследовании. с другой стороны, линкер хочет найти реализацию функций и глобальных переменных в вашем коде.

Теперь, когда вы используете ClassTwo в File1.cpp, компилятор ничего не знает об этом и не знает, сколько памяти должно выделяться для него или, например, членов witch, которые у него есть, или это класс и перечисление или даже typedef of int, поэтому компиляция будет скомпилирована компилятором. добавив File2.cpp решить проблему компоновщика, который ищет реализацию, но компилятор все еще недоволен, потому что он ничего не знает о вашем типе.

Итак, помните, что на этапе компиляции вы всегда работаете только с одним файлом (и, конечно, с файлами, которые входят в этот файл), а на этапе ссылок вам нужно несколько файлов, содержащих реализации. и поскольку C/С++ статически типизированы, и они позволяют их идентификатору работать во многих целях (определение, typedef, enum class,...), поэтому вы всегда должны идентифицировать свой идентификатор для компилятора, а затем использовать его, и, как правило, компилятор должен всегда знайте размер вашей переменной!!