• 06--谈谈:C++类的“包含”机制


    谈谈:C++类的“包含”机制

     

          本人在学习Qt的时候发现了一个非常有趣的现象。有很多函数的调用方法都写成了如下的形式:

    object.func().func2();

      这令小弟着实不懂。在上面这段代码中,第一个对象调用它的成员函数func()是完全没有问题的,但是后面那个func2()就奇怪了。我们只知道,点运算符(.)的作用就是调用对象的成员,但是如果按照上面这个程序的字面意思来理解,就是对象object调用它的成员函数func(),然后函数func()再调用它的成员函数func2()。这怎么能解释得通哩??我们只知道对象有成员函数,但是从来没有听说过函数也可以有成员函数的啊。没有办法,只有翻C++的工具书,最后,居然发现了这个原来就是C++中的“包含”思想。那么究竟何为包含呢,且听小弟慢慢叙来......^_^

          何为“包含”,其实说白了就是一个类可以包含另一个类的对象。即如下程序所示:

      

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    class A
    {
                       //...
     
    };
     
    class B
    {
                       //...
        A a;
        A b;
    };

      在上面这个程序中,我们定义了类A和类B。其中类B里面我们定义了类A的两个对象a和b。这样的情况就叫类B包含了类A。下面,我们用一个程序来看一下“包含”:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    #include <iostream>
    using namespace std;
    class A
    {
    public:
        A(int i){x=i;cout<<"调用A类的构造函数 ";}
        ~A(){cout<<"调用A类的析构函数 ";};
        void get() {cout<<"A类中X的值为:"<<x<<endl;}
    private:
        int x;
    };
     
    class B
    {
    public:
        B(int i,int j,int k):a(i),b(j),y(k){cout<<"调用B类的构造函数 ";}
        A geta(){return a;}
        A getb(){return b;}
        ~B(){cout<<"调用B类的析构函数 ";}
        void gety(){cout<<"B类中y的值为:"<<y<<endl;}
    private:
        A a;
        A b;
        int y;
    };
     
    int main()
    {
        B b(1,2,3);
        b.geta().get();
        b.getb().get();
        b.gety();
        return 0;
    }
    • 首先是对两个类进行分析:在上面这个程序中,我们定义了两个类A和B。其中可以看到,在类B的私有成员变量里面,我们定义了一个类B自己的成员变量,另外还定义了两个类A的对象a和b(22行和23行);另外在类B的公有函数中,我们定义了两个返回值为类A的函数:geta()和getb(),它们的作用就是返回在类B中定义的两个类A的对象a和b。在这里我们特别应该注意的是类B的构造函数:
      B(int i,int j,int k):a(i),b(j),y(k){cout<<"调用B类的构造函数 ";}

      这个构造函数很有意思。我们可以看到它不仅初始化了自己的私有成员变量y,而且也顺带初始化了类A的两个对象a和b。那么它肯定会调用类A的构造函数,而且会调用两次。然后再调用一次B类自己的构造函数。那么析构的时候顺序应该就是相反的,首先调用B类的析构函数,然后再调用两次A类的析构函数。我们可以看到后面的程序输出图这样说滴,^_^。(见输出的红色框和黄色框)

    • 现在我们再来看一看主函数中的东东。首先在程序的第29行,我们定义了B类的对象b,并调用了A类和B类的构造函数初始化了类A的对象a、b和类B的对象b。然后在程序的第30行我们就可以看到在博文一开始介绍的Qt中的东东。这里我们就搞不懂了,它们到底是干啥用的,什么都不说了,先看一下运行结果:

            我们可以看到,返回的类A的对象a中x的值为1,另外一个类A的对象b中x的值为2。好了,豁然开朗了,我们来解释一下程序第30行和31行。第29行用类B的对象b来调用成员函数geta(),该函数是在17行定义的,作用就是返回类A的对象a,因此第30行

      b.geta().get();

            就相当于

      A a(1);
      a.get();

            这里的原因就是,因为b.geta()返回的是x的成员值为1的对象a,所以再调用类A的get()函数就可以省略了对象a了。那么同理,程序第31行就相当于

      A b(2);
      b.get();

            这就说明了类B可以通过成员函数来访问被包含的类A对象的成员变量。就是文章一开始提到的方式,其实它是隐藏了声明类A的对象,因为由于包含的原因,类B已经帮类A搞定了对象的声明了~~~

          OK咯,解决了Qt这个问题,我也顺带地搞懂了包含这个概念,嘿嘿......好了,收工!!!

  • 相关阅读:
    2032 杨辉三角
    2023 求平均成绩
    幸运数
    扑克牌大小
    single-number
    合唱队
    Problem A: 【字符串】最长回文子串
    Problem A: 最大连续子序列
    数串
    02CSS3基本语法05
  • 原文地址:https://www.cnblogs.com/wohenben/p/5413405.html
Copyright © 2020-2023  润新知