1. 程式人生 > >c++類和類之間的關係

c++類和類之間的關係

//類就是體現封裝的思想,有許可權的控制
//程式追求的最高境界是;高內聚(函式功能越單一越好,目標越專一越好),低耦合(類與其他類關係越少越好)
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <string>

using namespace std;

class A
{
public:
private:
    int a;
};

//類與類關係1:
//類B包含有類A的成員變數,即B has A//類B依賴於類A,誰包含誰,誰就依賴於誰,因為類A的物件要先於類B建立,等類A物件建立完才能完成類B物件的建立,所以類B依賴於類A
class B
{
public:
private:
    A a;//當物件A不存在無參建構函式時,需要顯示的寫出初始化函式列表
};

//類與類關係2:
//類A是類C成員方法的形參,即C use A//類C依賴於類B,但耦合度類C明顯低於類B
class C
{
public:
    void funcC(A a)
    {
    
    }
private:
};

//類與類關係3:
//類D繼承於A,D是A的子類,A的程式碼都存在於類D的內部,即B is A//類D依賴於類A,繼承的耦合度是極高的,但可以增加程式碼的重複使用
class D:public A
{
public:

private:
};

//類與類的關係3--類的繼承
class Student
{
public:
    Student(int id, string name):age(10)
    {
        this->name = name;
        this->id = id;
    }
    void print()
    {
        cout << "name:" << this->name << endl;
        cout << "id=" << this->id << endl;
    }
private:
    int id;
    const int age;
    string name;
};

//c++程式碼的可重用性通過繼承機制來實現
//父類為基類,子類為派生類
class Student1 :public Student//類Student1繼承了Student,子類包含父類
{
public:
    /*
    //下面三段程式碼是錯誤的,首先Student1是Student的子類,Student1物件建立過程為先構造父類物件,在建立子類額外的變數,但父類Student要構造的話得先滿足它的建構函式,即和初始化構造列表一樣,指定怎麼構造父類,滿足父類的建構函式
    Student1()
    {
    }
    */
    //這兒也是函式初始化列表,與類裡有別的類物件構造基本差不多,需要把包含的別的類的物件先構造好,再構造自己的
    //不同的是繼承是在類開頭繼承,而類裡有別的類物件則是包含在私有成員變數中,且繼承建立父類的物件為匿名物件,且呼叫的時候繼承是直接呼叫,類裡有別的物件則需要先呼叫別的物件,再用別的物件呼叫其內部事物
    //子類先呼叫父類的建構函式建立一個空間(其實物件本質也就是空間),然後再呼叫子類本身的建構函式建立空間
    Student1(int id, string name, int score) :Student(id, name)
    {
        this->score = score;//這兒更能表明子類其實是包含父類物件的,函式初始化列表已經幫我們構造出父類物件,子類物件只要建立額外的變數並賦值,然後包含父類物件即可
    }
    void print()
    {
        Student::print();//這是表明呼叫的是父類裡的方法,因為父類的物件為匿名物件,所以其方法的呼叫使用作用域形式呼叫
        /*
        注意子類是沒有辦法直接呼叫父類的私有成員變數的,雖然子類物件包含父類物件,但從程式碼上子類的私有成員變數並沒有含有父類的私有成員變數,這其實又滿足了私有成員變數只能在類內部訪問的規則
        或者說子類物件雖然包含了父類物件,但父類物件對子類物件仍有訪問許可權控制,父類的私有成員變數子類是訪問不到的,父類的公有成員變數子類可以訪問到
        下面兩段程式碼都是錯誤的
        Student::id = 1;
        this->id = 1;
        */
        cout << "score=" << this->score << endl;
    }
private:
    int score;
};

class Parent
{
//這兒的public是訪問許可權
public:
    int t1;//類的內部和外部都能訪問
protected:
    int t2;//類的內部可以訪問,類的外部不可以訪問,子類也可以訪問
private:
    int t3;//類的內部可以訪問,類的外部不可以訪問,
};

//三種繼承方式,最好使用公有繼承,其他兩種繼承基本不使用
//這兒的public是繼承方式,即公有繼承
//public公有繼承時
//1.子類內部可以直接訪問父類的public成員變數,子類的物件在類外部也可以直接訪問父類的public成員變數
//2.子類內部可以直接訪問父類的protected成員變數,子類的物件在類外部不可以直接訪問父類的protected成員變數
//3.子類內部不可以直接訪問父類的private成員變數,子類的物件在類外部也不可以直接訪問父類的private成員變數
class Child1 :public Parent
{
public:
    void func()
    {
        t1 = 100;
        t2 = 200;
    }
};

//這兒的protected是繼承方式,即保護繼承,繼承過來的物件除private變數外,其他都為protected訪問許可權,即子子類可以內部訪問public和protected成員變數
//protected保護繼承時
//1.子類內部可以直接訪問父類的public成員變數,子類的物件在類外部不可以直接訪問父類的public成員變數
//2.子類內部可以直接訪問父類的protected成員變數,子類的物件在類外部不可以直接訪問父類的protected成員變數
//3.子類內部不可以直接訪問父類的private成員變數,子類的物件在類外部也不可以直接訪問父類的private成員變數
class Child2 :protected Parent
{
public:
    void func()
    {
        t1 = 100;
        t2 = 200;
    }

};

//這兒的private是繼承方式,即私有繼承,繼承過來的變數都為private訪問許可權,即子子類不可在類內部訪問任何父類成員變數
//private私有繼承時
//1.子類內部可以直接訪問父類的public成員變數,子類的物件在類外部不可以直接訪問父類的public成員變數
//2.子類內部可以直接訪問父類的protected成員變數,子類的物件在類外部不可以直接訪問父類的protected成員變數
//3.子類內部不可以直接訪問父類的private成員變數,子類的物件在類外部也不可以直接訪問父類的private成員變數
class Child3 :private Parent
{
public:
    void func()
    {
        t1 = 100;
        t2 = 200;
    }
};
//總結:
//繼承方式本質是用來區分被繼承過來的變數在子類的物件中是屬於public成員變數,還是protected成員變數,還是private成員變數
//即子類的物件在類外部對繼承過來的變數使用許可權和這個子類又被子子類繼承時這個子子類內部和外部對繼承過來的變數的使用許可權
//即本質上就是確定子類繼承過來的物件是public,protected,private哪個訪問許可權
//繼承方式對繼承過來的變數的限制規則:對許可權大的變為繼承許可權,許可權小的保留

int main()
{
    Parent p;
    
    return 0;
}