在Visual C++中进行类设计的通行做法(上)——类的搭建

本文由荔园微风分享,他是一位有25年经验的IT专家,讨论了在VisualC++中进行类设计的常见做法。他强调了将类定义和函数声明放在头文件(*.h),而实现放在源文件(*.cpp)中的重要性,并通过一个例子介绍了如何构建项目,包括创建头文件、源文件以及类的继承。他还提到了使用VisualStudio2022添加文件的两种方法,并解释了#pragmaonce指令的作用。
摘要由CSDN通过智能技术生成

我是荔园微风,作为一名在IT界整整25年的老兵,今天我们来重新审视一下在Visual C++中进行类设计的通行做法,这一篇帖子先来看看如何把架构搭建起来。程序员新手会去看很多书,但是书中往往教语法多,讲程序员习惯的少。那我们就来谈谈这个话题。

先来看一个重点,下面这一段话一定要记住。

在Visual C++中设计一个类的时候,程序员通常喜欢这样做:

(1)将类的定义及类成员函数的声明放到头文件(*.h文件)中。

(2)将类中成员函数的实现放到源文件(*.cpp文件)中。

我还是延用我在之前的帖子《Visual C++中的虚函数和纯虚函数的原理》中所讲的例子来继续今天的话题。所以大家要先看一下我的这个帖子:

Visual C++中的虚函数和纯虚函数的原理

假如主文件是study.cpp,对于Father类另外需要father.h和father.cpp 两个文件。那么对于Son类需要son.h和son.cpp两个文件。对于main()函数,按照程序员的通行做法,是要把他单独放到study.cpp文件中。

下面开始构建这个项目,首先在某一个解决方案中添加一个新项目study,依然选择“Windows控制台应用程序”,这将会自动生成一个study.cpp。接下来我们就将Father类和Son类的定义各自拆分成两个文件:头文件和源文件。在多项目的解决方案中,要将该项目设置为启动项目。

程序员在往一个现有项目中添加头文件(.h文件)或源文件(.cpp文件)有两种方式:

第一种方式

是在“解决方案资源管理器”中,找到要添加文件的项目,在该项目下,在“头文件”节点上单击鼠标右键,在弹出菜单中选择【添加】→【新建项】。在接下来的“添加新项”对话框中,选中“头文件(.h)”,输入文件名:father.h。单击“添加”按钮,完成father.h头文件的添加。

接下来,在“解决方案资源管理器”窗口中,在“源文件”节点上单击鼠标右键,在弹出菜单中选择【添加】→【新建项】,在出现的“添加新项”对话框中,选中“C++文件(.cpp)”,输入文件名:father.cpp,然后单击“添加”按钮完成添加。过程和添加头文件类似。

然后再用相同的做法把Son类的头文件和源文件设置一下。

第二种方式

是直接添加类,Visual Studio 2022开发环境会自动给你提供头文件和源文件。在“解决方案资源管理器”窗口中,直接在项目上单击鼠标右键,在弹出菜单中选择【添加】→【类】,出现添加类对话框。

在类名框中输入Father,在.h文件框中输入Father.h,在.cpp文件Father.cpp。

如果是Son类,还要在基类框中输入Father。访问的话就填写public。

输入类名和基类的名字后,单击“确定”按钮,完成添加。

提示:Visual Studio 2022生成的头文件中包含了#pragma once指令代码,我们先将其注释起来,后面会解释该句代码的作用。

各文件代码

father.h代码如下所示。

//在头文件中包含类的定义及类成员函数的声明
class Father
{
public:
  Father();
  ~Father();
  void eat();
  void run();
  virtual void study();
};

father.cpp代码如下所示。

//在源文件中包含类中成员函数的实现
#include "pch.h"

//因为在编译 father.cpp时,编译器不知道 father到底是什么,所以要包含father.h,这样,
//编译器就知道 father是一种类的类型
#include "father.h"
 
#include <iostream>
using namespace std;

//::叫作作用域标识符,用于指明一个函数属于哪个类或一个数据成员属于哪个类。::前面如果不跟
//类名,则表示是全局函数(即非成员函数)或全局数据
Father:: Father()
{
}

Father:: ~Father()
{
}

//注意:虽然我们在函数体中什么也没写,但仍然是实现了这个函数
void Father:: eat()
{
}
  
void Father:: run()
{
}

//注意,在头文件(.h文件)中加了virtual后,在源文件(.cpp文件)中就不必再加virtual了
void Father:: study()
{
  cout<<"study"<<endl;
}

这里要说明一下,在包含头文件时,<>和" "有什么区别?<>和" "表示编译器在搜索头文件时的顺序不同,<>表示从系统目录下开始搜索,然后再搜索PATH环境变量所列出的目录,不搜索当前目录;" "表示先从当前目录搜索,然后是系统目录和PATH环境变量所列出的目录。所以如果我们知道头文件在系统目录下,就可以直接用<>,这样可以加快搜索速度。

son.h代码如下所示。

//因Son类从Father类继承而来,要让编译器知道Father是一种类的类型,就要包含Father.h头文件
#include "father.h"

class Son: public Father
{
public:
  void study ();
};

son.cpp代码如下所示。

#include "pch.h"
#include "son.h"
#include <iostream>
using namespace std;

void Son:: study ()
{
  cout<<"new study"<<endl;
}

study.cpp代码如下所示。

#include "pch.h"
#include "father.h"
#include "son.h"

void fn(Father *p)
{
  p->study ();
}

int main()
{
  Father *p;
  Son st;
  p=&st;
  fn(p);
  return 0;
}

这样,架构就搭好了,那么这样一个框架能搭出来,说明你具有程序员的一个基本素质,就是构建,那么是不是这样就好了呢,就能正常运行了呢?很遗憾,程序很难一次性通过,你们说气不气人,要怎么进行调整和排错呢,请看我的下一篇帖子。

作者简介:荔园微风,1981年生,高级工程师,浙大工学硕士,软件工程项目主管,做过程序员、软件设计师、系统架构师,早期的Windows程序员,Visual Studio忠实用户,C/C++使用者,是一位在计算机界学习、拼搏、奋斗了25年的老将,经历了UNIX时代、桌面WIN32时代、Web应用时代、云计算时代、手机安卓时代、大数据时代、ICT时代、AI深度学习时代、智能机器时代,我不知道未来还会有什么时代,只记得这一路走来,充满着艰辛与收获,愿同大家一起走下去,充满希望的走下去。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值