2

我知道,只要有可能,我们将使用前向声明而不是包含来加快编译速度。

我有这样的课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 <string>避免std::string在代码中使用时出现编译错误。这里如何使用前向声明来避免编译错误?可能吗?

谢谢。

4

5 回答 5

4

自从string用作

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

将需要整个结构string,因此必须需要声明。你必须#include <string>


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;),当您实际使用它时,由于类型冲突,编译将失败。

于 2010-06-07T11:55:14.093 回答
2

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

因此,如果你这样Student定义

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

上述任何一个班级成员都会迫使您#include在标题中使用 Person.h 。

您很好理解,前向声明有助于避免编译依赖,从而减少编译时间。但是,这主要涉及用户定义的标头,因为这些标头会经常更改。标准库头文件不会更改,因此在这些情况下节省的空间并不大。

于 2010-06-07T11:52:56.143 回答
1

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

于 2010-06-07T11:52:30.963 回答
0

也许还考虑使用继承。

#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)
 };
于 2010-06-07T11:58:36.680 回答
0

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

于 2010-06-07T12:10:36.967 回答