对内置数据类型使用前向声明

发布于 2024-09-04 07:59:26 字数 939 浏览 5 评论 0原文

我明白,只要有可能,我们就应该使用前向声明而不是包含来加快编译速度。

我有一个像这样的Person类。

#pragma once

#include <string>

class Person
{
public:
    Person(std::string name, int age);
    std::string GetName(void) const;
    int GetAge(void) const;
private:
    std::string _name;
    int _age;
};

和一个像这样的类 Student

#pragma once

#include <string>

class Person;

class Student
{
public:
    Student(std::string name, int age, int level = 0);
    Student(const Person& person);
    std::string GetName(void) const;
    int GetAge(void) const;
    int GetLevel(void) const;
private:
    std::string _name;
    int _age;
    int _level;
};

在 Student.h 中,我有一个前向声明 class Person; 来在我的转换构造函数中使用 Person 。美好的。但我已经做了 #include 以避免在代码中使用 std::string 时出现编译错误。这里如何使用前向声明来避免编译错误?是否可以?

谢谢。

I understand that wherever possible we shall use forward declarations instead of includes to speed up the compilation.

I have a class Person like this.

#pragma once

#include <string>

class Person
{
public:
    Person(std::string name, int age);
    std::string GetName(void) const;
    int GetAge(void) const;
private:
    std::string _name;
    int _age;
};

and a class Student like this

#pragma once

#include <string>

class Person;

class Student
{
public:
    Student(std::string name, int age, int level = 0);
    Student(const Person& person);
    std::string GetName(void) const;
    int GetAge(void) const;
    int GetLevel(void) const;
private:
    std::string _name;
    int _age;
    int _level;
};

In Student.h, I have a forward declaration class Person; to use Person in my conversion constructor. Fine. But I have done #include <string> to avoid compilation error while using std::string in the code. How to use forward declaration here to avoid the compilation error? Is it possible?

Thanks.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

蒲公英的约定 2024-09-11 07:59:26

使用string作为

std::string _name;
//^^^^^^^^^ concrete member    

由于需要 string的整体结构,因此必须需要声明。您必须#include


如果您编写的话,可以省略string的声明,例如

std::string* _name;
//^^^^^^^^^^ pointer or reference

您可以使用前向声明,但我仍然建议您不要这样做,因为std: :string 不是像 Person 或 Student 这样的简单结构类型,而是一个非常复杂的类型,涉及很多模板:

template<class charT, class traits = char_traits<charT>, class Allocator = allocator<charT> >
class basic_string { ... };
typedef basic_string<char> string;

如果你向前声明错误(例如 class string;),编译将失败当您因类型冲突而实际使用它时。

Since used string as

std::string _name;
//^^^^^^^^^ concrete member    

the whole structure of string would be needed, so the declaration must be needed. You must #include <string>.


Declaration of string can be omitted possible if you write, e.g.

std::string* _name;
//^^^^^^^^^^ pointer or reference

which you could use a forward declaration, but I still recommend you not to do so, because std::string is not a simple structure type like Person or Student, but a very complex type involving many templates:

template<class charT, class traits = char_traits<charT>, class Allocator = allocator<charT> >
class basic_string { ... };
typedef basic_string<char> string;

If you forward declare it wrongly (e.g. class string;), the compilation will fail when you actually use it because of conflicting type.

生生漫 2024-09-11 07:59:26

您只能将前向声明与指针和引用一起使用(因为它们具有固定大小,与它们引用的对象的大小无关)。如果按值使用特定类,编译器需要其完整定义(以便知道其确切大小),因此前向声明是不够的。

因此,如果您像这样定义 Student

class Student
{
public:
    ...
    Student(const Person person);
    ...
private:
    Person person;
};

上述任一类成员都会强制您在标头中添加 #include Person.h。

您很清楚,前向声明有助于避免编译依赖,从而减少编译时间。然而,这主要涉及用户定义的标头,因为这些标头可能会经常更改。标准库头不会改变,因此在这些情况下节省并不重要。

You can only use forward declarations with pointers and references (because these are of a fixed size, independent of the size of the object they refer to). If you use a specific class by value, the compiler needs its full definition (in order to know its exact size), thus forward declaration is not enough.

Thus, if you define Student like this

class Student
{
public:
    ...
    Student(const Person person);
    ...
private:
    Person person;
};

either of the above class members would force you to #include Person.h in your header.

You understand well, that forward declaration helps avoiding compilation dependencies, thus reduces compilation time. However, that concerns mainly user-defined headers, because these are the ones that can change frequently. Standard library headers are not going to change, so the saving is not significant in those cases.

明明#如月 2024-09-11 07:59:26

您只能使用前向声明进行类型标识,例如在函数/方法指针参数原型中使用声明的类型时。如果您要声明一个成员变量(即 std::string _name;),编译器需要的内容比前向声明所能提供的要多一些。例如,如果有人执行 sizeof(Student) ,则编译器必须有权访问整个声明才能计算出大小。

You can only use forward declarations for type identification, such as when you use the declared type in a function/method pointer parameter prototype. If you are going to declare a member variable (i.e. std::string _name;) the compiler needs a little bit more than a forward declaration can give it. For example, if someone does a sizeof(Student) the compiler has to have access to the entire declaration to figure out the size.

那支青花 2024-09-11 07:59:26

也许还可以考虑使用继承。

#include "Person.h" // i am afraid you need to

class Student : public Person
{
     ...

     protected:
         int _level;
         // no name and age, that is inhertianced from person
         // (if you want to access them from student, you maybe need to make them protected)
 };

Maybe also consider to use inheritance.

#include "Person.h" // i am afraid you need to

class Student : public Person
{
     ...

     protected:
         int _level;
         // no name and age, that is inhertianced from person
         // (if you want to access them from student, you maybe need to make them protected)
 };
绮筵 2024-09-11 07:59:26

前向声明用于减少包含并解决循环依赖关系。但是,当在类的公共或受保护接口中使用转发时,您需要将包含正确头文件的负担交给类的用户。
除此之外,STL 中定义的转发类型可能无法按预期工作。例如,std::string 可以定义为 typedef basic_string;字符串;。使用 namespace std{ class string;} 向前声明它会给你一个编译错误。

Forward declarations are used to reduce include and to resolve cyclic dependencies. But when using forwards in the public or protected interface of your class, you place the burden of including the correct header files to the users of your class.
Beside this, forwarding types defined in the STL may not work as expected. For example, std::string might be defined as typedef basic_string<char> string;. Declaring it forward with namespace std{ class string;} will give you a compilation error.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文