从结构struct谈到类class(基于C++实现)

深入理解struct

 在C语言中,我们通常使用struct来表示不同数据类型的结合。当然我们也可以在struct中定义函数,在C++中,这是允许的但是不提倡使用,因为有一个比它更好使用的复杂数据类型,叫做类(这在稍后做出介绍)。

   使用struct的时候有一个问题:在进行一个比较大的项目工程的时候,我们的数据结构的定义和使用可能在不同的文件中,当我们修改了数据结构中的某个成员,那么,使用该数据结构的函数必须修改,而我们并不知道拿下函数使用该种数据结构,这时候我们怎么做?答案很简单,在函数定义的时候,让该函数属于该数据结构,在再次查找修改函数的时候,只要属于该结构的函数就进行修改就好了,代码如下:

声明数据结构:
struct Time{
    int hour;
    int minute;
    int second;
    void set_time(int h, int m, int s); 
    void tick();
    void show();
    void run();
};
定义函数:
void Time::set_time(int h, int m, int s){}
void Time::tick(){}
void Time::show(){}
void Time::run(){}

补充:成员运算符:表示某个变量的成员,‘.’;表示某个类型的成员,“::”;

类的引出

   这样定义就万事大吉了吗?我们如果在其他函数中试图访问该结构中的成员变量(如:hourminutesecond)是成功的,这样我们就有可能无意中修改了数据结构中的某个成员变量的值,当其他函数在使用成员变量的时候,就会使用该可能非法的数据,这样我们就会想到只要让这些成员变量变成私有的就好了,这样除了结构中定义的函数外,其他方式都不可以访问到该成员,这就出现了我们C++常使用的一种数据结构——类。我们进行如下修改。

声明数据结构:
class Time{
    int hour;
    int minute;
    int second;
    void set_time(int h, int m, int s); 
    void tick();
    void show();
    void run();
};
定义函数:
void Time::set_time(int h, int m, int s){}
void Time::tick(){}
void Time::show(){}
void Time::run(){}

如果我们就止步于上面的数据结构,我们定义一个上述类的对象,当我们通过对象调用函数的时候,会发现编译不会通过,提示我们“你访问的对象是私有的”。这里就要说明classstruct最大的区别:struct中的所有成员默认是公开的(public),即任意一个函数都可以进行访问;class中的所有成员默认是私有的(private),即除了class中的成员函数之外,其他方式不可以访问。

我们使用class而不是用struct的原因是因为,我们想让成员变量变成私有的,实现基本数据封装。但是对于成员函数的调用接口我们不必要私有,因为我们创建的对象,要通过成员函数完成项目任务,所以我们应让成员函数的接口公开(public),这就是我们常说的封装。接着进行如下更改,让成员函数变量公有的(public)。

声明数据结构:
class Time{
private:
    int hour;
    int minute;
    int second;
public:
    void set_time(int h, int m, int s); 
    void tick();
    void show();
    void run();
};
定义函数:
void Time::set_time(int h, int m, int s){}
void Time::tick(){}
void Time::show(){}
void Time::run(){}

在这里我们要说说class中成员变量的访问权限:

1private:私有的。这是class中成员变量默认的访问权限,这种权限的成员变量,只有该类中成员函数可以访问,子类中的成员函数不可以访问,其他方式也不可以访问。(子类是继承中的概念,在讲继承的时候再谈这个话题,先了解就好)。

2protected:保护的。该class中的成员函数可以访问,子类中的成员函数也可以访问,但是其他方式不可以访问。

3public:公开的。该class中的成员函数可以访问,子类中的成员函数也可以访问,其他方式亦可以访问。

 构造函数和析构函数

对于class中的成员函数,我们可以自己写一个函数进行初始化,比如set函数,将每个成员变量进行初始化赋值。但是每次创建一个新类都要调用该种函数进行成员的初始化,这大大加大了我们创建使用类的代价,为了让我们每次创建一个对象的时候,都可以自动调用某个函数进行成员变量的初始化,我们可以使用类中重要的成员函数——构造函数(构造函数无返回值,并且函数名与类名一致),它可以在创建对象的时候自动调用,根据创建对象时传入的初始化参数进行成员变量的初始化。

构造函数的格式:Class_name(parameters){}

构造函数的初始化有两种方式:

1)通过在构造函数内部进行赋值进行初始化,常量不能被赋值,只能使用初始化列表。

2)通过初始化列表进行初始化,如果成员变量是数组或结构不能使用初始化列表进行初始化。

构造函数的重载:有时候我们需要定义多个构造函数,因为我们可能基于不同的需求对成员变量的初始化操作不同,这就是构造函数的重载(函数重载:函数名相同,但是函数参数不同。系统可以根据传入参数的不同来调用不同的函数)。

析构函数:存在构造函数也就会存在析构函数,析构函数就是在该对象即将被释放的时候做收尾动作,析构函数一定没有参数列表,所以析构函数不可以重载。

  析构函数规则:~Class_name(){} 

class A{
     int n;
     double d;
 public :  A():n(0),d(0.0){   // constructor_init1
         }
         A(int n){        // constructor_init2
             this->n = n; 
             d = 0.0;           
         }
         void show(){
             cout << "n = " << n << ", d = " << d << endl;
         }
         ~A(){
            cout << “~A()” << endl;
         }
};
int main(int ac, char *av[])
{
    A a1;            // use constructor_init1
a1.show();
    A a2(100);        // use constructor_init2
    (*this).show();
    return 0;
}

   this指针:this指针是系统自动定义的,用来保存结构变量的地址。当我们创建一个对象的时候,系统就会自动将该对象对应的类的成员保存在this中,我们可以通过this->mem_valthis->mem_func,来访问该成员。在一个成员函数中,可以不用写this,表示默认使用该成员函数所在类的成员变量。

   构造函数总结:

   (1)构造函数不同写返回值,其函数名与类名一致。

 (2)构造函数在每个对象创建的时候都不被自动调用一次。

 构造函数的调用顺序

    ·全局对象的构造函数在main之前调用。

    ·静态局部对象的构造函数在整个程序的执行过程中只调用一次。

class A{
   int n;
public:
   A(int n) : n(n){
         cout << "A(" << n << ')' <<  endl;
    }   
    ~A(){
        cout << "~A(" << n << ')' << endl;
    }   
};
void func(){
    A a2(2);
    static A a3(3);
}
int main(int ac, char *av[])
{
    A a4(4);
    cout << "first call func : \n";
    func();
    cout << "second call func : \n";
    func();
 
    return 0;
}
A a1(1); 
//==========================
// 1:全局对象
// 2:函数func中的自动对象
// 3:函数func中的静态全局对象
//4:函数main中的自动对象
//===============================
结果显示:
[root@anna-laptop construtor]# ./call_queue 
A(1)  
A(4)
first call func : 
A(2)
A(3)
~A(2)
second call func : 
A(2)
~A(2)
~A(4)
~A(3)
~A(1)



本文出自 “11219885” 博客,请务必保留此出处http://11229885.blog.51cto.com/11219885/1762927

本页内容版权归属为原作者,如有侵犯您的权益,请通知我们删除。
此篇h3c-IRF的实战配置,同样与前面华为的堆叠一样路子,我们先聊聊为啥要做这个?为什么不玩双机,要玩IRF。其实弄懂这一点,对于售前来讲,在外面做方案也是思路相当清晰的一点。 以前我们常规的双机方案如下图: 架构特点: 1.全网无单点故障,完整的解决因为单电源或者单一设备故障引起的业务不可用。 2.核心交换区-使用华为stack堆叠(前面有文章单独介绍) 3.防火墙HA(Juniper-NSRP协议,不懂度娘)(可能大家会问题,防火墙到华为交换机为什么没做lacp或者aggregate,大家注意下防火
HA专题: Corosync+Pacemaker+drbd实现MySQL高可用 大纲 前言 实验拓扑 实验环境 实验步骤 安装前准备工作 配置DRBD 配置MySQL 配置Corosync+Pacemaker 测试 我遇到的问题 总结 前言 上篇文章我们介绍了 drbd 的相关原理、编译安装、简单的实现. drbd 虽然可以保证数据的可靠性但是我们上次的实现还有很多的缺陷,这次我们将 drbd 定义为HA集群的一个资源,可以实现让多个节点自动切换 drbd 的主从模式并结合 MySQL 实现其数据的高可用

在实践中深入理解ARP协议 - 2016-04-18 15:04:18

0.说明 本文为我个人计划撰写的博客专题 《在实践中深入理解常见网络协议》 中关于ARP协议的一篇 , 有兴趣的朋友可以继续关注我的博客,我将会陆续撰写各种协议的实践分析文章。 在同一个网络(无特别说明,均指以太网络)中进行通信的主机,必须要拥有目标主机的MAC地址才能够正确地将数据发送给目标主机,那么如何知道目标主机的MAC地址呢?可以通过ARP协议。ARP协议就是用来获取目标IP地址所对应的MAC地址的,也就是说,ARP协议可以动态地在三层IP地址和二层MAC地址之间建立一种映射关系。可以用如下示意图
昨天把nginx的日志进行了切割,关于如何切割nginx日志,可以查看《 烂泥:切割nginx日志 》这篇文章。 今天打算分析下nginx日志,要分析nginx日志,我们可以通过shell脚本和第三方软件awstats进行分析,在此我们选择的是通过第三方软件awstats进行分析。 要使用awstats分析nginx日志,我们要安装awstats,而在安装awstats之前,我们需要先来介绍下awstats是什么? 一、awstats是什么 awstats是一个免费非常简洁而且强大有个性的基于Perl语言

Linux磁盘管理工具LVM2详解 - 2016-04-18 14:04:52

一、LVM简介 LVM2(LogicalVolume Manage,Version2):它是Linux环境下对 磁盘分区 进行管理的一种机制,将一个或多个底层块设备组织成一个逻辑设备。通过LVM 管理员 可以轻松管理磁盘分区,使用LVM与传统的分区方法相比有很多的优势,如:容量的分配 更加灵活、逻辑卷的扩展和缩减更加方便、使用snapshot(快照)来备份数据也非常方便。通过本文你可 以快速了 解LVM2的使用方法。 二、LVM2 使用详解 (该图片来源于网络) PV:Physical Volume 物理
前几天客户的系统做升级,需要用到 Azure CLI ,客户那边新来的小朋友根据我给的教程连了一个下午都没连上。他告诉我之后,我火速帮他查到底哪出了问题,一直把报错的截图拿过来分析。我自己试了好几次都可以连上没问题。最后的最后,当我找到问题出在哪儿的时候,我简直是一脸小动物。好了,最靠谱的永远是自己。自己写一篇给客户好了。不废话开始做。 使用 Azure CLI 连接到订阅,有一个必要条件,那就是,必须要安装 CLI 。哈哈。 关于安装 CLI 的几种方法,如何安装。可以参考 Microsoft Azur
一台生产业务的虚拟机假死,强行关机后无法POWER ON。在启动时报虚拟机文件被锁定,错误信息如下: 此时对虚机进行迁移、快照等,发现操作不可用。查看虚机状态,发现其在集群内的三台物理主机上来回飘。 解决方法: 1、首先将cluster中的HA功能关闭。如果该功能不关闭,容易造成死锁,,VM不断跳动,,不断的在不同的ESXI内循环被锁,徒劳而无功。 2、虚机磁盘文件被锁,必须要知道到底是哪台ESXI把他给锁住了,这是关键。 3、在VCenter中,把被锁的VM从Inventory中remove掉。原因很简
最近在参与负责某线上MySQL项目时,客户要求 实现SQL数据备份、复原和前滚的全自动 化。 在RHEL平台下 使用Perl语言编写脚本同时结合cron指令 来共同实现,整个过程很轻松顺利且效果也比较满意。 同时,由于所负责的另一个项目是线下DB2环境,那么在 Windows Server平台下又该如何实现DB2数据库备份、复原和前滚的自动化 呢? 因为Windows远没有Linux的命令行功能强大,所以实现起来稍微曲折些,但是基本上还是可以实现的。经过简单的编写和测试通过后,现抽空将实现思路和实验代码分

在实践中深入理解IP协议 - 2016-04-11 18:04:38

0.说明 本文为我个人计划撰写的博客专题 《在实践中深入理解常见网络协议》 中关于IP协议的一篇 ,有兴趣的朋友可以继续关注我的博客,我将会陆续撰写各种协议的实践分析文章。 TCP/IP协议栈其实当然不止有TCP和IP两个协议,但以这两个协议作为这个协议栈的统称,足以体现出其在TCP/IP协议栈中的重要性,正是因为有了IP协议,才使得不同网络间可以进行通信。当然要提及IP协议,其实还需要分析与其相关的配套协议,如ICMP、IGMP、ARP,这些协议与IP协议的关系可如下: 不过这里我们只关注于IP协议中的
OSSIM平台安全事件关联分析实践 在《开源安全运维平台OSSIM最佳实践》一书中叙述到,事件关联是整个OSSIM关联分析的核心,对于OSSIM的事件关联需要海量处理能力,主要便于现在需要及时存储从设备采集到的日志,并能关联匹配和输出,进而通过WebUI展示。从实时性上看,关联分析的整个处理过程不能间断,这对系统的实时性要求较高,另外Ossim系统是基于规则的,Ossim内部具有多套高速规则分析引擎,以实现模式匹配和对关联分析结果调用。所以系统的关联引擎是一个典型数据处理系统,必须依靠强大的数据库做支撑,