04/28/2020
C++类的不完全声明
类的基本思想是数据抽象和封装。 数据抽象是一种依赖于接口和实现分离的编程以及设计技术。 1
- 类的接口包括用户所能执行的操作,接口更注重易于使用。
- 类的实现则包括类的数据成员、负责接口实现的函数体以及定义类所需的各种私有函数。实现更注重高效
封装实现了类的接口和实现的分离,隐藏了实现细节。
区分.h和.cpp文件
- .h 文件是头文件,只能预编译,用来拷贝到其他文件去的
- .cpp 文件是编译文件,需要被编译成目标文件的
区分声明,定义
- 声明使得名字为程序所知,定义负责创建与名字关联的实体
- 变量声明规定了变量的类型和名字,在这一点上与定义相同,但是定义还申请存储空间,也可能会为变量赋一个初始值
- 声明可以多次,定义只能一次
- 声明不需要函数体,或者类体,定义需要,一对花括号
- 函数声明不需要参数名字
- 定义为某一特定类型的变量申请存储空间,可以选择初始化该变量。名字必须在定义或申明之后才能使用。
void print(int); //函数声明
class C;//声明,前向声明
class C{//定义
public:
void test(); //成员函数的声明
void test2()//内联函数 是定义
{
}
};
void print(int a) //定义
{
cout << a;
}
类的声明:我们也能仅仅声明类而暂时不定义它
- 前向声明: 它向程序引入了名字Screen并且指明Screen是一种类类型。
例子1:
class Screen; //前向声明
int main(){
Screen* s;
Screen& s2 = *s;
Screen fowardDeclare(Screen&);
}
所以说Screen是一个不完全类型,在声明之后但是在定义之前。
- 可以定义指向这种类型的指针或引用
- 也可以声明(但是不能定义)以不完全类型作为参数或者返回类型的函数。
例子2:
class C
{
C c; //错误的,不完全类型
C* c;// 正确的,指针类型的
};
对于一个类来说,在我们创建它的对象之间该类必须被定义过,而不能仅仅被声明。否则,编译器就无法了解这样的对象需要多少存储空间。同时,如果只有声明,也不能访问其成员。
互相包含的头文件,并使用对方的对象的问题
A.h
#include "B.h"
class A
{
public:
A();
B b; //使用B的对象,编译器必须明确知道B需要的内存空间,B定义完之后
};
A.cpp
A::A()
{
}
B.h: 注意这里没有include A 文件
class A;
class B
{
public:
B();
A* a; //前向声明A,不能使用A的对象,只能使用指针,因为指针的内存空间是确定的
//A a; //错误的, 不完全类型
};
B.cpp 重点引用A
#include "A.h" //注意这里需要include A的文件,因为A的头文件引用了B的头文件
B::B()
{
a = new A;
}
C++ primer 第五版 7.1,7.3.3 ↩︎