我有一类车辆(vehicle.h和vehicle.cpp)。如果我没有将包含在头文件中,Visual Studio会给我错误。为什么是这样?在我之前的2个作业中,我将包含在.cpp文件中并且没有任何问题。这是我想要工作但不是:
vehicle.h:
#ifndef VEHICLE_H
#define VEHICLE_H
using namespace std;
class Vehicle
{
public:
Vehicle();
Vehicle(string mfr, int cylinders, Person owner);
string getManufacturer();
int getNumOfCylinders();
Person getOwner();
private:
string manufacturer;
int numOfCylinders;
Person owner;
};
#endif
vehicle.cpp:
#include <iostream>
#include <string>
using namespace std;
#include "person.h"
#include "vehicle.h"
Vehicle::Vehicle()
{
//Initialize with defaults
}
Vehicle::Vehicle(string mfr, int cylinders, Person owner)
{
//Initialize with parameters
}
string Vehicle::getManufacturer()
{
return manufacturer;
}
int Vehicle::getNumOfCylinders()
{
return numOfCylinders;
}
Person Vehicle::getOwner()
{
return owner;
}
person.h:
#ifndef PERSON_H
#define PERSON_H
class Person {
public:
//default constructor
Person();
//constructor with two parameters
Person(string the_name, string no);
//accessor member functions
string get_name() const;
string getDriverLicenseNo() const;
//overloaded equal operator
bool operator==(const Person& p);
//overloaded extraction operator
friend istream& operator >> (istream& in, Person& p);
//overloaded insertion operator
friend ostream& operator <<(ostream& out, Person& p);
private:
string name;
string drivingLicenseNo;
};
#endif
person.cpp:
#include <iostream>
#include <string>
using namespace std;
#include "person.h"
//default constructor
Person::Person(){}
//constructor with two parameters
Person::Person(string the_name, string no){}
//accessor member functions
string Person::get_name() const
{
return name;
}
string Person::getDriverLicenseNo() const
{
return drivingLicenseNo;
}
//overloaded equal operator
bool Person::operator==(const Person& p)
{
return false;
}
//overloaded extraction operator
istream& operator >> (istream& in, Person& p)
{
return in;
}
//overloaded insertion operator
ostream& operator <<(ostream& out, Person& p)
{
return out;
}
truck.h:
#include "vehicle.h"
class Truck: public Vehicle
{
};
truck.cpp:
#include "person.h"
#include "vehicle.h"
//implement truck here
例如错误:
错误C2061:语法错误:标识符'字符串'
错误C2146:语法错误:缺少';'在标识符“getManufacturer”之前
错误C2061:语法错误:标识符'字符串'
错误C2535:'Person :: Person(void)':已定义或声明的成员函数
错误C2146:语法错误:缺少';'在标识符'get_name'之前
错误C4430:缺少类型说明符 - 假设为int。注意:C ++不支持default-int
错误C4430:缺少类型说明符 - 假设为int。注意:C ++不支持default-int
错误C2146:语法错误:缺少';'在标识符'getDriverLicenseNo'之前
答案 0 :(得分:3)
您在车辆头文件中声明Person
的实例,因此编译器需要完整声明。如果您使用指针或对某人的引用,您可以简单地使用class Person;
向前声明它。
编辑:另外,取出using namespace std;
并在变量前加上std::
。它将来会拯救很多球。
EDIT2:您还需要在头文件中加入<string>
。
好的,接下来,我会尽量保持简洁。
当您的编译器处理您的实现文件(.cpp)时,它包含您指定的标头(在本例中为vehicle.h
和person.h
)。对于每个实现文件,编译器需要知道您使用的每个类型,以便它可以生成正确的代码。
当它处理包含文件时,仍然需要了解所有内容。因此,在vehicle.h
标头文件中,您使用的是Person
。在编译器遇到这种情况时,它需要知道如何构造人。您的vehicle.cpp
在person.h
之前包含vehicle.h
,所以没问题。 FOR vehicle.cpp
。包含vehicle.h
但不包含person.h
的任何其他内容都会给您编译错误。
那么你什么时候可以使用前向声明和用户指针或引用?
声明指针或引用不需要告诉编译器有关头文件中的类或结构的任何信息。你只是告诉编译器你有意这样做。前提是该类是向前宣布的:
class Person;
然后编译器说“okee dokee,我会接受的。”然后在实现中包含相关文件,编译器会看到你的意思,并且每个人都会从酒吧里走回家。
我认为,您的案例中发生的事情是,车辆的实施文件在纸面上看起来不错,但其他内容包括vehicle.h
,并且不知道Person
是什么。< / p>
您的解决方案
如果必须,请在person.h
中包含vehicle.h
,否则请更改该构造函数以引用person(和成员),并转发声明Person
。但是,不知道你的程序在做什么,我不能说即使按引用传递也是正确的。
请删除using namespace std;
并将string
更改为std::string
:)
答案 1 :(得分:1)
当您将另一个类的对象放入您的类时,编译器需要知道该类的整个定义。记住这条规则的最简单方法是在你知道sizeof(Person)之前意识到你不能知道sizeof(Vehicle),编译器也不知道。如果先进行前向声明,则指针和对另一个类的引用都可以。
答案 2 :(得分:1)
person.h是否包含行#include "vehicle.h"
?循环依赖在C ++中难以管理,例如Java或C#。您可以在#include "Person.h"
之前轻松进入需要#include "Vehicle.h"
的情况,但在#include "Vehicle.h"
之前还需要#include "Person.h"
。
在许多情况下,你必须告诉编译器“Person是一个类的名称,但我还没准备好给你定义”。为此你可以说class Person;
这解开了循环引用问题。
另外,制作Person
对象的大量副本可能没有意义,但这就是你在传递值时所做的事情。它看起来像是来自Java或C#环境,其中类类型的变量自动(并且始终)是引用。在C ++中,您必须通过Person*
(指针,可以更改为指向不同的实例,如Java和C#引用)或Person&
(C ++引用,永久附加)来请求引用特定情况)。