程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> 關於C++ >> VC++入門經典學習筆記

VC++入門經典學習筆記

編輯:關於C++

1.面向對象的基本思想:

類是為適應特定應用程序的需求而定義的數據類型。面向對象編程中的類同時定義了與程序相關的對象。設計該問題的解決方案時,要根據某個問題所特有的對象,使用可以直接處理這些對象的操作。我們可以定義一個類來表示某種抽象的事物,如數學概念中的復數,或者物理概念中的開車。因此,除了是數據類型之外,類還可以定義現實世界中特定種類的一組對象,至少可以說是解決特定問題所需要的定義。

我們可以認為類定義了一組特定事物的特性,這種事物用一組公共的參數來表示,並使用用一組公共的,可以對它們進行處理的操作。可以應用於特定類對象的操作由類接口定義。它們對應於類定義的public部分包含的函數。

現實世界中有許多不同種類的箱子,如紙板箱,電腦機箱,糖果盒。說出來的只是很少的幾個,我們肯定還能想到好多。從這幾個箱子中,我們可以發現某些共同的特性–都是四方形的。因此,我們可以將某種箱子定義成具有所有箱子的一般特性:只是長,寬和高,然後給基本的箱子類型添加一些其他特性,從而將特定種類的箱子同其他箱子區別開來。我們還可能發現一些可以對特定種類的箱子執行,但不能對其他箱子執行的操作。

因此,相對准確地模擬現實世界的好方法,就是定義相互關聯的類。可以將糖果盒視為具備所有基本箱子的特性,再加上少許自身特性的箱子。這句話准確地闡明了以某個類為基礎定義另一個類時類之間的關系。更特殊化的類具有父類的所有特性,再加上少許區別性的自身特性。

2.類的繼承

當以一個類為基礎定義另一個類時,後者稱為派生類。派生類自動包含用來定義自己的那個類的所有數據成員,還有條件地包含了函數成員。我們說該類繼承了基類的數據成員和函數成員。
注意:派生類不繼承的基類成員僅有析構函數,構造函數以及任何重載賦值運算符的成員函數。所有的其他成員都將由派生類繼承。不繼承某些基類成員的原因是派生類總是有自己的構造函數和析構函數。如果基類有賦值運算符,派生類也將提供自己的版本。我們說不繼承這些函數,意思是它們不會作為派生類對象的成員存在。但它們任然作為某個對象的基礎組成部分而存在。

3.基類的概念

任何用作定義其他類的基礎的類都是基類。例如:如果直接根據類A定義類B,則A是B的直接基類。
僅僅因為繼承了成員函數,並不意味著不需要在派生類中將它們替換成新版本,必要時當然可以這樣做。

4.基類的派生類

1.創建win32控制台空白項目,添加CBox.h頭文件

#pragma once             //防止多次嵌入Box.h。
class CBox
{
public:
    double m_Length;
    double m_Width;
    double m_Height;
    explicit CBox( double lv = 1.0, double wv = 1.0, double hv = 1.0 ):m_Length{ lv }, m_Width{ wv }, m_Height{ hv }{}
};

2.添加CCandyBox.h頭文件

#pragma once
#include 
#include "CBox.h"

class CCandyBox :private CBox                            //默認為私有繼承,如果要訪問基類數據成員,
    //則需要改變訪問說明符。如果省略基類的訪問說明符,則編譯器將默認該說明符是private。
{
public:
    char* m_Contents;
    explicit CCandyBox(const char* str = "Candy")
    {
        size_t length{ strlen(str) + 1 };
        m_Contents = new char[length];
        strcpy_s(m_Contents, length, str);
    }

    CCandyBox(const CCandyBox& box) = delete;
    CCandyBox& operator = (const CCandyBox& box) = delete;

    ~CCandyBox()
    {
        delete[] m_Contents;
    }
};

3.添加項目名稱.cpp源文件

#include 
#include "CCandyBox.h"

int main()
{
    CBox myBox{ 4.0, 3.0, 2.0 };                       //創建一個基類箱子對象
    CCandyBox myCandyBox;                              
    CCandyBox myMintBox{"Water Thin Mints"};           //創建一個糖果盒對象

    std::cout << "myBox occupies" << sizeof myBox
        << " bytes" << std::endl
        << "myCandyBox occupies " << sizeof myCandyBox
        << " bytes" << std::endl
        << "myMintBox occupies " << sizeof myMintBox
        << " bytes" << std::endl;

    std::cout << "myBox length is " << myBox.m_Length << std::endl;
    myBox.m_Length = 10.0;
    system("pause");
    return 0;
}

運行結果:

myBox occupies24 bytes
myCandyBox occupies 32 bytes
myMintBox occupies 32 bytes
myBox length is 4

5.派生類中構造函數的操作:

雖派生類不會繼承基類的構造函數,但它們仍然存在於基類中,並且用於創建派生類對象的基類部分。因為創建派生類對象的基類部分實際上屬於基於基類構造函數而非派生類構造函數的任務。畢竟,雖然在派生類中繼承了基類的私有成員,但是不可訪問,因此這些任務必須交給基類的構造函數來完成。

創建派生類對象的基類部分,自動調用了默認的基類構造函數。但情況不一定這樣。可以在派生類的構造函數 中安排調用特定的基類構造函數,這樣就能用非默認的構造函數初始化基類的數據成員,實際上就是可以根據給派生類構造函數提供的數據,選擇調用特定的類構造函數。

6.繼承類成員的訪問級別

如果在派生類的定義中沒有為基類提供訪問說明符,則默認的訪問說明符是private,結果是從基類繼承的public和protected成員在派生類中稱為private。基類的private成員仍然是基類所私有的,因此不能被派生類的成員函數訪問。事實上,無論派生類定義種為基類指定怎樣的訪問說明符,這些成員始終都是基類的私有成員。

  CCBox:CBox{};

我們還可以使用public作為基類的說明符。該說明符賦予派生類中的基類成員與原來相同的訪問級別,因此public成員仍然是public,protected成員仍然是protected。

 CCBox:public CBox{};

最後一種可能性是將基類聲明為protected,結果是從基類繼承的piblic成員在派生類中成為protected成員,而protected繼承的成員(和private繼承的成員)在派生類中仍然保持原來的訪問級別。

  CCBox:protected CBox{};

將其簡化為與派生類的繼承成員有關的3點:
如果將基類的成員聲明為private,則它們在派生類中永遠都不可訪問。
如果將基類聲明為public,其成員在派生類中的訪問級別保持不變。
如果將基類聲明為protected,其public成員在派生類中將成為protected。

能夠改變派生類中繼承成員的訪問級別,給予我們一定程度的靈活性,但不要忘記基類中指定的級別是不能放寬的。只能使訪問級別更加嚴格,這意味著如果想在派生類中改變訪問級別,則基類需要有public成員。這一點似乎與為了保護數據不受非授權訪問而將其封裝在類中的思想相侼,但如後面所述,經常需要以這樣的方式定義基類,因為它們的唯一用途是作為定義其他類的基礎,而非用來實例化對象。

7.派生類中的復制構造函數

注意:在聲明用相同的類對象初始化的對象時,會自動調用復制構造函數。

  CBox myBox{2.0,3.0,4.0};
  CBox copyBox{myBox};

第一條語句調用接受3個double類型實參的構造函數,第二條語句調用復制構造函數。如果不提供自己的復制構造函數,則編譯器將提供一個默認的復制構造函數,將初始化對象的成員逐一復制到新對象的對應成員中。

  CBox(const CBox& initB)
  {
    std::cout<<"CBox copy constructor called"<

注意:為了避免無窮無盡地調用自身,必須將復制構造函數的形參指定為引用,否則將需要復制以傳值方式傳遞的實參。當調用該示例中的復制構造函數時,它向屏幕上輸出一條消息,因此從輸出中可以看出事件發生的時間。現在需要做的只是向派生類中添加復制構造函數。

  CCandyBox(const CCandyBox& initB):CBox(initB)
  {
    std::cout<<"CCandyBox copy constructor called"<

注意:在為派生類編寫構造函數時,需要初始化包括繼承成員在內的派生類對象的所有成員。

8.禁止派生類final

有時需要確保不能把類用作基類,為此可以把類指定為final

  class CBox final
  {
    //代碼
  };

定義中類名後面的final修飾符告訴編譯器不允許從CBox類中派生。
注意:final不是關鍵字,只在這個上下文中有特殊的含義。不能把關鍵字用作名稱,但可以把final用作變量名。

9.友元類成員

友元函數有權自由訪問任何類成員。當然,我們沒有理由說友元函數不能是另一個類的成員。
1.新建CBottle.h

#pragma once
class CCarton;                //前置聲明
class CBottle
{
public:
    CBottle(double height, double d) : m_Height{ height }, m_d{ d }{}
public:
    double m_Height;
    double m_d;

    friend CCarton::CCarton(const CBottle& aBottle);
};

2.新建CCarton.h

#pragma once
class CBottle;             //前置聲明 
class CCarton
{
public:
    CCarton(const CBottle& aBottle);
private:
    double m_Height;
    double m_Width;
    double m_Length;
};

3.新建項目名稱.cpp

#include "CCarton.h"
#include "CBottle.h"

CCarton::CCarton(const CBottle& aBottle)
{
    m_Height = aBottle.m_Height;
    m_Length = 4.0*aBottle.m_d;
    m_Width = 3.0*aBottle.m_d;
}
  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved