發新話題

C++ Gossip - 物件基礎《封裝的進階議題》巢狀類別

C++ Gossip - 物件基礎《封裝的進階議題》巢狀類別

類別可以定義在另一個類別之中,這樣的類別稱之為巢狀類別或內部類別,內部類別只被外部包裹的類別所見,當某個Slave類別完全只服務於一個 Master類別時,您可以將之設定為內部類別,如此使用Master類別的人就不用知道Slave的存在。

一個巢狀類別通常宣告在"private"區域,也可以宣告在"protected"或"public"區域,一個宣告的例子如下:
class OuterClass {
private:
        class InnerClass {
            //  ....
        };
};


以下是個巢狀類別的簡單示範:
  • PointDemo.h
class PointDemo {
public:
    PointDemo(int);
    ~PointDemo();
   
    void show();
private:

    // Nested Class
    class Point {
    public:
        Point();
        Point(int, int);
        int x() { return _x; }
        int y() { return _y; }
        void x(int x) { _x = x; }
        void y(int y) { _y = y; }
    private:
        int _x;
        int _y;
    };
   
    Point **_points;
    int _length;
};
實作內部類別定義時,必須同時指定外部類別與內部類別,中間以::連結,例如:
  • PointDemo.cpp
#include <iostream>
#include "ointDemo.h"
using namespace std;

// 實作內部類別
PointDemo:oint:oint() {
    _x = 0;
    _y = 0;
}

// 實作內部類別
PointDemo:oint::Point(int x, int y) {
    _x = x;
    _y = y;
}

PointDemo::PointDemo(int length) : _length(length) {
    _points = new Point*[_length];
    for(int i = 0; i < _length; i++) {
        _points = new Point();
        _points->x(i*5);
        _points->y(i*5);
    }     
}

void PointDemo::show() {
    for(int i = 0; i < _length; i++) {
        cout << "(x, y) = ("
             << _points->x() << ", "
             << _points->y() << ")"
             << endl;
    }
}

PointDemo::~PointDemo() {
    for(int i = 0; i < _length; i++) {
        delete _points;
    }     
    delete [] _points;
}

使用PointDemo的使用者不必知道Point類別的存在,直接呼叫show()函式就可以顯示Point資料:
  • main.cpp
#include <iostream>
#include "ointDemo.h"
using namespace std;

int main() {
    PointDemo demo(10);
    demo.show();   
    return 0;
}

執行結果:
(x, y) = (0, 0)
(x, y) = (5, 5)
(x, y) = (10, 10)
(x, y) = (15, 15)
(x, y) = (20, 20)
(x, y) = (25, 25)
(x, y) = (30, 30)
(x, y) = (35, 35)
(x, y) = (40, 40)
(x, y) = (45, 45)

在巢狀類別結構中,外部類別不能存取內部類別的私用成員,如果想要存取內部類別的私用成員的話,必須宣告其為friend,例如:
class PointDemo {
    ...
    friend class Point;

private:
    // Nested Class
    class Point {
        ....
    };
    ....
};


同樣的,內部類別不可存取外部類別的私用成員,如果要存取私用成員的話,必須宣告其為friend,例如:
class PointDemo {
public:
    ...
    friend class Point;

private:
    // Nested Class
    class Point {
        ....
        friend class PointDemo;
        ....
    };
    ....
};

存取外部類別的非靜態成員時,必須透過物件、指標或是參考,而不是直接呼叫。

您也可以將內部類別獨立定義在一個檔案中,例如:
  • PointDemo.h
class PointDemo {
public:
    PointDemo(int);
    ~PointDemo();
   
    void show();
private:

    // Nested Class
    class Point;
   
    Point **_points;
    int _length;
};

  • Point.h
class PointDemo::Point {
public:
    Point();
    Point(int, int);
    int x() { return _x; }
    int y() { return _y; }
    void x(int x) { _x = x; }
    void y(int y) { _y = y; }
private:
    int _x;
    int _y;
};

  • PointDemo.cpp
#include <iostream>
#include "ointDemo.h"
#include "Point.h"
using namespace std;

PointDemo::PointDemo(int length) : _length(length) {
    _points = new Point*[_length];
    for(int i = 0; i < _length; i++) {
        _points = new Point();
        _points->x(i*5);
        _points->y(i*5);
    }     
}

void PointDemo::show() {
    for(int i = 0; i < _length; i++) {
        cout << "(x, y) = ("
             << _points->x() << ", "
             << _points->y() << ")"
             << endl;
    }
}

PointDemo::~PointDemo() {
    for(int i = 0; i < _length; i++) {
        delete _points;
    }     
    delete [] _points;
}

  • Point.cpp
#include "PointDemo.h"
#include "Point.h"

PointDemo::Point::Point() {
    _x = 0;
    _y = 0;
}

PointDemo::Point::Point(int x, int y) {
    _x = x;
    _y = y;
}

TOP

發新話題

本站所有圖文均屬網友發表,僅代表作者的觀點與本站無關,如有侵權請通知版主會盡快刪除。