C++学习笔记(四): 类、头文件、对象

news2024/10/7 8:23:25

一个类定义了一个类型,以及与其关联的一组操作。

类机制是C++最重要的特性之一。实际上,C++最初的一个设计焦点就是能定义使用上像内置类型一样自然的类类型(class type)。

在这里插入图片描述

#include <iostream>
 
using namespace std;
 
class Box
{
   public:
      double length;   // 长度
      double breadth;  // 宽度
      double height;   // 高度
      // 成员函数声明
      double get(void);
      void set( double len, double bre, double hei );
};

为了使用标准库设施,我们必须包含相关的头文件。类似的,我们也需要使用头文件来访问为自己的应用程序所定义的类。习惯上,头文件根据其中定义的类的名字来命名。

// 成员函数定义
double Box::get(void)
{
    return length * breadth * height;
}
 
void Box::set( double len, double bre, double hei)
{
    length = len;
    breadth = bre;
    height = hei;
}
#include <iostream>
#include "Box.h"

int main( )
{
   Box Box1;        // 声明 Box1,类型为 Box
   double volume = 0.0;     // 用于存储体积
   
   // box 1 详述
   Box1.height = 5.0; 
   Box1.length = 6.0; 
   Box1.breadth = 7.0;
   
   // box 1 的体积
   Box1.set(16.0, 8.0, 12.0); 
   volume = Box1.get(); 
   return 0;
}

1.认识头文件

此程序以两个#include指令开始,其中一个使用了新的形式。
包含来自标准库的头文件时,也应该用尖括号(<>)包围头文件名。
对于不属于标准库的头文件,则用双引号(" ")包围。

1.1 C++为什么会有头文件?

为什么不扫描所有.c文件,然后把其中的函数定义都找出来,生成统一的一个声明文件,以后编译每个.c文件的时候都依赖这个文件就可以了。类似于java那样。
原因如下:
(1)如果编译器想成功编译并链接某个源码文件,需要知道两点信息:数据类型和重定位信息。以Java为例,Java二进制包内存放有数据类型信息和重定位信息;而C++二进制库符号表内只存放了重定位信息,因此,若想成功编译链接C++源码,还需要头文件告知编译器数据类型信息。而早期的硬件存储空间还是运算能力都还不太够,通过.h/.c手动的把声明和实现分开来解决问题是个非常简单有效的办法。
(2)C语言设计之初是没有头文件的,数据都是定长的。但是后来出现了 short int 、long int ;char等类型,函数的调用者不知道压栈的长度。例如函数add(x,y)调用:应该是先压2个字节、再压4个字节喃,还是先压4个字节,再压2个字节;还是连续压2个4字节?在这种情况下,函数调用需要提前声明,以便让调用者得知函数的参数与返回值尺寸。
(3)C++最初是作为C语言的扩展而开发的,因此它继承了C语言的一些特性,例如单独编译和模块化设计。C++有头文件是要兼容C,而 C++ 的Module包含元数据信息还在委员会讨论之中。
(4)使用头文件的好处是可以将代码分为接口和实现两部分,接口定义在头文件中,实现定义在源文件中。这样可以避免每次都重新编译整个程序,提高编译速度。还可以有效地隐藏实现细节,提高代码的可读性和可维护性。
(5)此外,使用头文件还可以方便地共享代码,因为多个源文件可以包含同一头文件,从而共享其中的代码。

头文件(header)使类或其他名字的定义可被多个程序使用的一种机制。程序通过#include指令使用头文件。

1.2 如何编写头文件?

头文件通常包含那些只能被定义一次的实体,如类、const和constexpr变量等。头文件也经常用到其他头文件的功能。

编写头文件头文件常用的技术是预处理器

在C++中,预处理器是一种在编译之前对源代码进行预处理的程序。它主要用于实现一些在编译时无法完成的任务,例如包含头文件、宏定义、条件编译等。

(1)包含头文件:使用#include指令可以包含头文件,以便访问其中定义的函数、变量、类等内容。

#include <iostream>
#include "myheader.h"

(2)宏定义:使用#define指令可以定义一个宏,以便在源代码中使用。宏可以定义一个常量、一个函数、一个代码块等。

#define PI 3.1415926
#define MAX(a, b) ((a) > (b) ? (a) : (b))

(3)条件编译:使用#if、#ifdef和#ifndef等指令可以进行条件编译,以便根据条件选择编译不同的代码。
例如,我们使用#ifdef和#endif指令进行条件编译,当定义了DEBUG宏时,输出Debug mode;否则,输出Release mode。

#ifdef DEBUG
    cout << "Debug mode" << endl;
#else
    cout << "Release mode" << endl;
#endif

(4)文件包含:使用#include指令可以包含其他源代码文件,以便将多个源代码文件组合成一个程序。例如,我们使用#include指令包含了myheader.h和mysource.cpp两个源代码文件,以便将多个源代码文件组合成一个程序。

#include "myheader.h"
#include "mysource.cpp"

预处理器的主要作用是在编译之前对源代码进行处理,以便生成一个新的源代码文件,这个文件包含了预处理器指令所表示的内容。预处理器可以使代码更加模块化、可读、易于维护,从而提高编程效率和代码质量。

编写头文件时应该遵循以下规范:

(1)头文件应该包含防止重复包含的预处理器指令。例如,使用#ifndef、#define和#endif指令可以防止头文件被多次包含。

正确用法:

#ifndef MYCLASS_H
#define MYCLASS_H

#include <iostream>

// MyClass类的声明
class MyClass {
public:
    MyClass(int count);
    void print();
private:
    int m_count;
};

// MyClass类的实现
MyClass::MyClass(int count) : m_count(count) {}

void MyClass::print() {
    std::cout << "count = " << m_count << std::endl;
}

#endif

错误示例:

//包含了同一个头文件myheader.h两次
//并没有使用#ifndef、#define和#endif等预处理器指令来防止重复包含,从而导致链接错误。
#include "myheader.h"
#include "myheader.h"

(2)头文件应该包含必要的声明和定义,但不应该包含不必要的内容。例如,不应该在头文件中包含函数的实现代码,因为这会导致多个源代码文件包含同一个实现代码,从而导致链接错误。

错误示例1:

//多次包含同一个头文件
#include <iostream>
#include <iostream>

错误示例2:

//包含了string头文件,但是并没有在程序中使用string类型或相关函数。
//这样会增加编译时间和可执行文件大小,降低程序的性能。
#include <iostream>
#include <string>

(3)头文件应该使用全局唯一的命名规范,避免与其他头文件或变量名称冲突。一般建议使用项目名或类名作为头文件的前缀,例如MyClass.h。

(4)头文件应该避免包含其他头文件,除非这些头文件是必需的。如果必须包含其他头文件,应该在头文件中使用前向声明来避免循环包含。

错误示例:

//包含了myheader.h头文件,但在函数中使用了MyClass类型,却没有使用前向声明来告知编译器这个类型的存在。
//这会导致编译器无法在编译函数前找到MyClass类型的定义,从而导致编译错误。
#include "myheader.h"

// 使用MyClass类型
void func(MyClass obj) {
    // ...
}

正确用法:

// 前向声明MyClass类
class MyClass;

// 使用MyClass类型
void func(MyClass obj) {
    // ...
}

// 包含MyClass类的头文件
#include "myclass.h"
//在上面的代码中,我们使用class MyClass;语句进行了MyClass类的前向声明
//然后在函数中使用了MyClass类型。
//最后,我们包含了MyClass类的头文件myclass.h,以便访问MyClass类的实现。

关于前向声明的解释:

// Forward declaration of class B
class B;

// Class A uses class B
class A {
public:
    void doSomething(B& b);
};

// Class C uses class A and class B
class C {
public:
    void doSomethingElse(A& a, B& b);
};

// Class B definition
class B {
public:
    void doSomething();
};

// Implementation of A::doSomething()
void A::doSomething(B& b) {
    b.doSomething();
}

// Implementation of C::doSomethingElse()
void C::doSomethingElse(A& a, B& b) {
    a.doSomething(b);
    b.doSomething();
}

在这个例子中,类C同时使用了类A和类B,如果直接在类C的头文件中包含类A和类B的头文件,很容易造成循环包含。使用前向声明可以避免这个问题。同时,由于类A和类B的定义分别在其他头文件中,所以在类A和类B的头文件中也必须使用前向声明来避免循环包含。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/574763.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

撰写博客如何获得持续的关注和支持

完成一篇如何获得铁粉&#xff0c;或者相关的文章且质量分达到80分以上即可 最近的博客都是在AI主导下完成的&#xff0c;大数据和大模型的优势的确有不可取代的强大优势&#xff0c;这种优势超过了撰写8年博客加入CSDN18年所有经验和努力的总和。 是的&#xff0c;AI和大数据的…

IPv4 和 IPv6 的特点、区别以及在互联网中的应用

在当今互联网时代&#xff0c;IP 地址是连接和通信的基础。IPv4&#xff08;Internet Protocol version 4&#xff09;和 IPv6&#xff08;Internet Protocol version 6&#xff09;是两种常见的 IP 地址版本。IPv4 是最早广泛使用的 IP 地址协议&#xff0c;而 IPv6 则是 IPv4…

chatgpt赋能python:Python循环结束的方式

Python循环结束的方式 在Python编程中&#xff0c;循环是一个非常重要的概念。循环是在程序中重复执行一段代码的方法。当满足特定条件时&#xff0c;循环可以继续执行&#xff0c;否则循环将结束。循环包括while循环和for循环两种方式。 while循环结束的方式 while循环是Py…

chatgpt赋能python:Python彩色输出:让代码更加生动有趣

Python 彩色输出&#xff1a;让代码更加生动有趣 如果你是一名Python程序员&#xff0c;那么你一定知道代码的可读性有多么重要。合理的排版和注释代码可以使你的代码更易于理解&#xff0c;但有时候你需要一些额外的工具来使代码更加生动有趣。这时候&#xff0c;Python 的彩…

腾讯云CVM服务器端口怎么开通?以开80端口为例

腾讯云CVM服务器端口是通过配置安全组规则来开通的&#xff0c;阿腾云以开通80端口为例来详细说下腾讯云轻量应用服务器开启端口的方法&#xff0c;其他的端口的开通如8080、1433、443、3306、8888等端口也适用于此方法&#xff0c;腾讯云服务器开通端口教程如下&#xff1a; …

chatgpt赋能python:Python取数字:一种简单而强大的方法

Python取数字&#xff1a;一种简单而强大的方法 Python是一种高级编程语言&#xff0c;被广泛用于数据分析、人工智能、Web开发等领域。在这个强大的语言中&#xff0c;我们可以使用非常简单的方法来提取数字&#xff0c;无论是从文本文件、数据库中&#xff0c;还是从互联网上…

新的交互流程:Ambire dApp 目录为Web3 的流畅旅程保驾护航

Ambire 钱包现在将 dApps 列入白名单&#xff0c;以提供丝滑又安全的用户体验。 尊敬的 Ambire 家人们&#x1f64c;&#xff0c;你们好&#xff01; 我们很高兴能与大家正式分享我们的 dApp 目录和插件系统 &#x1f389;。 你们中的一些人可能已经在你们的 Ambire 账户中注意…

chatgpt赋能python:Python坐标图:简单易用的数据可视化工具

Python 坐标图&#xff1a;简单易用的数据可视化工具 作为一种通用工具&#xff0c;Python 不仅在数据科学、自然语言处理、机器学习和深度学习等领域应用广泛&#xff0c;还在数据可视化方面表现出色。Python 的数据可视化库丰富多样&#xff0c;其中最受欢迎的就是 Matplotl…

chatgpt赋能python:Python微信群:一起探讨Python大家庭

Python 微信群&#xff1a;一起探讨Python大家庭 Python 微信群是一个由 Python 爱好者组成的大家庭&#xff0c;他们在这个平台上分享、交流、学习Python知识。在这个微信群中&#xff0c;你可以认识来自各行各业的Python工程师&#xff0c;可以发问、分享自己的经验和学习进…

GcExcel v6.1 支持新的 ‘.sjs‘ 模板文件 ‘.xltx‘ 格式 Crack

GrapeCity Documents for Excel (GcExcel) v6.1 版本现已上线&#xff01;该版本支持新的 SpreadJS .sjs 文件格式和 Excel 模板文件 .xltx 格式。此外&#xff0c;GcExcel 支持更多的SpreadJS兼容性功能和对 GcDataViewer 的多项增强。看看下面的主要亮点。 导入/导出 Spread…

chatgpt赋能python:Python循环两次:多次复制代码的快捷方式

Python 循环两次&#xff1a;多次复制代码的快捷方式 如果你是一名Python工程师&#xff0c;你可能已经会用循环复制代码了。然而&#xff0c;你是否知道可以循环两次来一次性复制代码呢&#xff1f;在这篇文章里&#xff0c;我们将介绍循环两次的方法&#xff0c;以及如何在代…

【分布族谱】均匀分布和三角形分布的关系

文章目录 均匀分布和三角分布均匀分布相加对数均匀分布 均匀分布和三角分布 均匀分布是最容易理解的连续随机分布&#xff0c;实际上就是等概率的连续分布&#xff0c;其PDF为 f ( x ) 1 b − a , x ∈ ( a , b ) f(x)\frac{1}{b-a}, x\in (a,b) f(x)b−a1​,x∈(a,b) 其样本…

chatgpt赋能python:Python嵌入-提高网站性能的最佳实践

Python 嵌入 - 提高网站性能的最佳实践 作为一名有10年Python编程经验的工程师&#xff0c;我想向大家介绍一下Python嵌入的概念以及如何将它应用于提高网站的性能。 什么是 Python 嵌入&#xff1f; Python嵌入是将Python解释器嵌入到其他应用程序中的过程。当Python解释器…

LOTL网络攻击技术越来越受欢迎

根据 APJ Darktrace 企业安全总监对 ACSC 及其五眼联盟合作伙伴本周发布的声明的回应&#xff0c;“离地生活”攻击技术越来越受欢迎。 Living off the land (LOTL) 是一种无文件恶意软件或 LOLbins 网络攻击技术。 网络罪犯使用受害人系统中的本机合法工具来维持和推进攻击。…

chatgpt赋能python:Python字段截取入门指南

Python字段截取入门指南 在Python中&#xff0c;对于字符串和列表等容器类型的对象&#xff0c;经常需要对其中的字段或元素进行截取。本篇文章将为您介绍Python中常用的字段截取方法&#xff0c;并提供一些示例&#xff0c;让您快速上手。 字符串字段截取 从头开始截取 如…

chatgpt赋能python:Python坐标转换:从经纬度到UTM

Python 坐标转换&#xff1a; 从经纬度到UTM Python 是一种高级编程语言&#xff0c;它在数据科学和地理信息系统领域中越来越受欢迎。在本文中&#xff0c;我们将讨论如何使用 Python 进行坐标转换&#xff0c;特别是从经纬度到 UTM&#xff08;通用横轴墨卡托投影&#xff0…

chatgpt赋能python:Python小数进位:从保留小数点后几位到基数进位

Python 小数进位&#xff1a;从保留小数点后几位到基数进位 Python 是一种易学易用的编程语言&#xff0c;特别适合初学者和专业工程师。它不仅支持整数和浮点数等基本数据类型&#xff0c;还提供了许多有用的内置函数和模块&#xff0c;其中包括浮点数进位方法和库。 本文将…

chatgpt赋能python:Python如何安装软件包

Python如何安装软件包 Python是一种广泛使用的编程语言&#xff0c;因其易学易用和灵活性而受到了许多程序员的欢迎。在Python中&#xff0c;安装各种软件包是必不可少的。本文章将向您介绍如何使用Python安装软件包。 什么是软件包&#xff1f; 在Python中&#xff0c;软件…

chatgpt赋能python:Python埋点:优化网站流量和数据分析的利器

Python埋点&#xff1a;优化网站流量和数据分析的利器 在现代商业运营中&#xff0c;网站流量和数据分析是非常重要的&#xff0c;因为这些数据对于业务指标和商业决策至关重要。而Python埋点技术&#xff0c;是现代网站优化和数据分析的利器&#xff0c;可以帮助企业更好地管…

微服务架构之注册中心

假设你发布了一个服务&#xff0c;并且已经在一台机器上部署了服务&#xff0c;那如果我想调用这个服务&#xff0c;我该如何知道你部署的这台机器的地址呢&#xff1f; 这个问题就跟我想去吃肯德基一样&#xff0c;我可以去谷歌地图上搜索肯德基&#xff0c;然后谷歌地图会返回…