拓冰建站拓冰建站
首页 / 资讯中心 / 正文

小学生学C++编程语法知识(如果想将某个类用作基类,为什么该类必须定义而并非声明)

如果想将某个类用作基类为什么该类必须定义而并非声明对小学生来说可以把它理解成继承就像“盖房子”建新房子之前必须知道老房子的完整结构而不能只知道一个名字。下面我们一步一步讲。一、先认识两个概念声明 vs 定义在 C 中1. 声明Declaration声明只是告诉编译器“有这么一个东西存在。”例如class Animal;这句话叫类的前向声明forward declaration意思“以后会有一个叫 Animal 的类。”但是编译器不知道Animal 有几个成员变量Animal 有哪些函数Animal 占多少内存它只知道有这么一个名字。2. 定义Definition定义就是完整写出类class Animal { public: int age; void eat() { cout 吃东西; } };现在编译器知道Animal有一个 int 类型的 age有一个 eat 函数大小是多少如何创建对象二、什么叫“作为基类”例如class Dog : public Animal { };意思Dog 继承 Animal。可以理解Animal | | DogDog 是 Animal 的孩子。三、为什么基类必须定义因为创建 Dog 的时候Dog 身体里面包含 Animal 的部分。例如class Animal { public: int age; }; class Dog : public Animal { };实际上Dog对象 ---------------- | Animal部分 | | | | age | ---------------- | Dog自己的部分 | ----------------Dog 天生带有 Animal。所以编译器必须知道Animal 到底有多大四、如果只有声明会发生什么例如class Animal; // 只有声明 class Dog : public Animal { };编译器看到Dog继承Animal它会问“Animal是什么样”可是它只知道Animal这个名字存在不知道Animal里面有什么所以无法计算Dog对象占多少空间例如Dog dog;编译器需要分配多少字节但是Animal??? 大小未知所以错误。五、用盖房子的故事理解假设爸爸 Animal 要给孩子 Dog 留房间。爸爸房间---------------- | 爸爸的房间 | | 10平方米 | ----------------孩子Dog 爸爸房间 自己房间那么建 Dog 房子之前必须知道爸爸房间多大。如果只听说“有一个爸爸。”但是不知道爸爸房间多大有几个房间怎么建所以继承必须知道基类完整结构。六、为什么普通指针可以只声明这里容易混淆。例如class Animal; Animal* p;可以。为什么因为指针大小固定。比如64位系统指针 8字节编译器只需要知道“这是一个地址。”不需要知道 Animal 有多大。但是class Dog : public Animal { };不行。因为Dog包含Animal。必须知道Animal大小七、一个经典对比情况1指向对象可以class Student; Student* p;因为只需要保存地址。情况2继承不可以class Student; class GoodStudent : public Student { };因为GoodStudent需要包含Student。八、还有一个重要原因虚函数表如果基类有虚函数class Animal { public: virtual void speak(); };那么对象里面还有虚函数表指针 vptr例如Animal对象 ------------- | vptr | ------------- | 成员变量 | -------------派生类Dog对象 ------------- | Animal部分 | | vptr | ------------- | Dog部分 | -------------如果不知道 Animal 定义连有没有虚函数有没有vptr内存布局都不知道。所以更加不能继承。九、总结成一句小学生能记住的话为什么基类必须定义因为派生类像是在基类身体上继续添加东西编译器必须先知道基类完整长什么样才能计算派生类的大小和布局。口诀声明 知道名字不知道身体 定义 知道身体知道大小 指针 只需要知道名字 继承 必须知道身体十、和前面“虚析构函数”的知识联系起来以后学习class Base { public: virtual ~Base() { } }; class Derived : public Base { };这里Derived继承Base。编译器必须知道Base完整定义。因为Derived对象里面包含Base部分。所以继承关系比指针关系要求更多的信息。这也是为什么class Base; Base* p; // 可以 class Derived : public Base { }; // 不可以这是 C 面向对象中非常核心的规则。
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门