C++小细节12-类的前向声明

04/28/2020


类的基本思想是数据抽象和封装。 数据抽象是一种依赖于接口和实现分离的编程以及设计技术。 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;
}

  1. C++ primer 第五版 7.1,7.3.3 ↩︎

猜你喜欢

转载自blog.csdn.net/weixin_44200074/article/details/105811989