類的概念、成員函數的定義方式、類的訪問控制和封裝、類的大小、this指針

文章目錄

  • 類的概念
    • struct
    • class
    • class和struct的區別是什么呢?
  • 類中成員函數的兩種定義方式
    • 聲明和定義都在類中
    • 聲明和定義分離
  • 類的訪問控制和封裝
    • 類的封裝特性
  • 類的大小
    • 結構體內存對齊規則
    • 類的存儲方式
  • this指針


類的概念

在C++中,類可以說是最重要的東西,因為C++一開始的定位就是c with class,也正是因為引入了類,才讓c++從c的面向過程思想轉變為面向對象的思想,關注的是對象,將一件事情拆分成不同的對象,靠對象之間的交互完成。

C++有兩種能夠創建類的方法

struct

第一種是struct,也就是從C繼承而來的,在C語言中,struct可以用來創建結構體,但是結構體中只能保存變量,而不能保存函數,在C++中,struct不僅可以用來創建類,還保留了C語言中結構體的用法

struct Date
{void PrintDate(){cout << _year << '-' << _month << '-' << _day << endl;}int _year;int _month;int _day;
};

class

class是C++中定義類的關鍵字,他的用法和struct類似。

在類中,類的元素被稱為類的成員,類中的數據被稱為成員變量或者類的屬性,類中的函數被稱為類的方法或者成員函數

class Date
{void PrintDate(){cout << _year << '-' << _month << '-' << _day << endl;}int _year;int _month;int _day;
};

class和struct的區別是什么呢?

  1. C++兼容C語言,所以struct不僅可以定義類,還可以當成結構體使用。
  2. 訪問限定不同,struct的成員默認訪問方式為public,class為private, 并且struct默認繼承為public繼承,,class為private

類中成員函數的兩種定義方式

聲明和定義都在類中

如果成員函數在類內部定義,則其是隱式的inline函數。

class Date
{void PrintDate(){cout << _year << '-' << _month << '-' << _day << endl;}int _year;int _month;int _day;
};

聲明和定義分離

在類內聲明,在類外定義,這樣能讓類更加簡潔,不那么臃腫,通常都是使用這種方式。

class Date
{void PrintDate();int _year;int _month;int _day;
};//需要通過作用域運算符指定這個方法屬于Date類
void Date::PrintDate()
{cout << _year << '-' << _month << '-' << _day << endl;
}

類的訪問控制和封裝

訪問限定符有三種,分別是public,private,protected
在這里插入圖片描述

  1. public修飾的成員在類外可以直接被訪問。
  2. protected和private修飾的成員在類外不能直接被訪問,protected修飾內容派生類可以訪問,private不可以。
  3. 訪問權限作用域從該訪問限定符出現的位置開始直到下一個訪問限定符出現時為止。

類的封裝特性

封裝:將數據和操作數據的方法進行有機結合,隱藏對象的屬性和實現細節,僅對外公開接口來和對象進行 交互。

封裝本質上是一種管理:我們如何管理兵馬俑呢?如果什么都不管,兵馬俑可能會被隨意破壞。那么我們首先建了一座房子把兵馬俑給封裝起來。但是我們目的并不是全封裝起來,不讓別人看。所以我們開放了售票通道,可以通過買票突破封裝、在合理的監管機制下進去參觀。類也是一樣,我們將類數據和方法都封裝一下。不想給別人肆意修改,我們使用protected/private把成員封裝起來。同時開放一些共有的成員函數對成員合理的訪問機制。所以封裝本質是一種管理。

一般對于對象的屬性,我們不希望別人對它進行修改,所以會用private將其封裝,但是我們又需要給別人提供獲取它的接口,所以會對方法和接口給與public屬性。


類的大小

class Date
{
public:void PrintDate();private:char a;int _year;int _month;int _day;
};

我們可以看到,類中有成員函數,有成員變量,那么類的大小是如何計算的呢?

int main()
{Date d;cout << sizeof(d) << endl;
}

在這里插入圖片描述
這里用sizeof查看大小,發現只有成員變量的大小(三個int類型一個char類型,3*4+1=13,這里的16是因為內存對齊偏移了3個字節),而沒有成員函數的大小

結構體內存對齊規則

  1. 第一個成員在與結構體偏移量為0的地址處。
  2. 其他成員變量要對齊到某個數字(對齊數)的整數倍的地址處。
    注意:對齊數 = 編譯器默認的一個對齊數該成員大小 兩者中的較小值。(如int大小為4,VS中默認的對齊數為8,取4)
  3. 結構體總大小為:最大對齊數(所有變量類型最大者與默認對齊參數取最小,本例中所有變量類型最大者是int,大小為4,與默認對齊參數取最小,則為4)的整數倍。
  4. 如果嵌套了結構體的情況,嵌套的結構體對齊到自己的最大對齊數的整數倍處,結構體的整體大小就是所有最大對齊數(含嵌套結構體的對齊數)的整數倍

類的存儲方式

為什么會只保存了成員變量呢?這里就要引申出類的存儲方式。

對于上面的類,如果我們將類實例化為多個對象,實際上這些對象不同的地方只有它的屬性,它們調用的方法都是完全相同的, 為了不重復保存這些代碼,C++只保存了屬性,而將方法放到了公共的代碼段中,來避免了空間的浪費。
在這里插入圖片描述
同時,如果一個類中什么都沒有,編譯器會給這個類一個字節,來唯一標識這個類。
在這里插入圖片描述
總結:類的大小就是成員變量之和(需要考慮內存對齊)


this指針

void Date::PrintDate()
{cout << _year << '-' << _month << '-' << _day << endl;
}

對于類中的成員函數,我們并沒有將對象的屬性傳給他,那么他是如何能夠獲取這些屬性的呢?

C++編譯器給每個“非靜態的成員函數“增加了一個隱藏的指針參數(this指針),讓該指針指向當前對象(函數運行時調用該函數的對象),在函數體中所有對成員變量的操作,都是通過該指針去訪問。只不過所有的操作對用戶是透明的,即用戶不需要來傳遞,編譯器自動完成。

其實類的成員函數中隱含了一個this指針,所以在編譯器處理的時候,上面的代碼等價于

void Date::PrintDate(Date * const this)
{cout << this->_year << '-' << this->_month << '-' << this->_day << endl;
}
  • 這個this指針的類型是類類型 * const this,之所以是頂層const的原因是因為this指針唯一指向對象地址。
  • this指針只能在成員函數中使用
  • this指針本質上其實是一個成員函數的形參,是對象調用成員函數時,將對象地址作為實參傳遞給this形參。所以對象中不存儲this指針,this指針存在寄存器中。
  • this指針是成員函數第一個隱含的指針形參,一般情況由編譯器通過ecx寄存器自動傳遞,不需要用戶傳遞,

同時,如果this指針為空時,成員函數使用到了this指針,則會崩潰,如果沒使用,則正常運行

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/443825.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/443825.shtml
英文地址,請注明出處:http://en.pswp.cn/news/443825.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

jQuery實現兩個列表框的值之間的互換:

jQuery實現兩個列表框的值之間的互換&#xff1a; 截圖如下&#xff1a; 代碼如下&#xff1a; <% page language"java" import"java.util.*" pageEncoding"UTF-8"%> <%String path request.getContextPath();String basePath reque…

類的6個默認成員函數:構造函數、析構函數、拷貝構造函數、重載運算符、三/五法則

文章目錄6個默認成員函數構造函數概念默認構造函數的類型默認實參概念默認實參的使用默認實參聲明全局變量作為默認實參某些類不能依賴于編譯器合成的默認構造函數第一個原因第二個原因第三個原因構造函數初始化構造函數里面的“”是初始化嗎&#xff1f;為什么要使用列表初始化…

C++ 類的知識 | 構造函數再探、匿名對象、友元函數、內部類、類的const成員、類的static成員

文章目錄構造函數再探以下代碼共調用多少次拷貝構造函數委托構造函數概念形式匿名對象友元友元的聲明友元類令成員函數作為友元函數重載和友元注意內部類特性類的const成員可變數據成員類的static成員概念關于static靜態成員的類內初始化靜態成員能用于某些普通成員不能的場景構…

截取全部數值字符并將其轉化為數值類型

功能 從name中找出全部數值字符&#xff0c;之后將name&#xff08;string類&#xff09;轉為d&#xff08;double類&#xff09; 代碼 #include <iostream> #include <list> #include <deque> #include <vector> #include <forward_list> #i…

替換string中的部分字符

功能 向函數fun中傳入三個參數&#xff1a;將s中所有oldval替換為newval 代碼 #include <iostream> #include <list> #include <deque> #include <vector> #include <forward_list> #include <array> using namespace std;void fun(str…

順序容器(vector、list、string、deque、forward_list)及迭代器、容器適配器

文章目錄概述所有容器都支持的操作迭代器迭代器支持的操作迭代器支持的算術運算容器類型size_typeiterator 和 const_iterator容器定義和初始化拷貝初始化順序容器獨有的構造函數&#xff08;array除外&#xff09;array的初始化與內置數組類型的區別6種初始化方法&#xff08;…

jQuery實現表格隔行換顏色:

jQuery實現表格各行換顏色&#xff1a; 截圖如下&#xff1a; 代碼如下&#xff1a; <span style"font-family:Microsoft YaHei;font-size:14px;"><% page language"java" import"java.util.*" pageEncoding"UTF-8"%> &…

用stack處理中綴表達式【+、-、*、/、()】

文章目錄題目描述思路使用getline()存儲輸入的字符串邊讀取邊壓棧完整代碼題目描述 使用stack處理括號化的表達式。當你看到一個左括號&#xff0c;將其記錄下來。當你在一個左括號之后看到一個右括號&#xff0c;從stack中pop對象&#xff0c;直至遇到左括號&#xff0c;將左括…

原地置換法尋找數組中重復的數

文章目錄題目描述代碼實現題目描述 在一個長度為 n 的數組 nums 里的所有數字都在 0&#xff5e;n-1 的范圍內。數組中某些數字是重復的&#xff0c;但不知道有幾個數字重復了&#xff0c;也不知道每個數字重復了幾次。請找出數組中任意一個重復的數字。 輸入&#xff1a; [2,…

二維數組的查找

文章目錄題目描述思路注意代碼題目描述 在一個 n * m 的二維數組中&#xff0c;每一行都按照從左到右遞增的順序排序&#xff0c;每一列都按照從上到下遞增的順序排序。請完成一個高效的函數&#xff0c;輸入這樣的一個二維數組和一個整數&#xff0c;判斷數組中是否含有該整數…

雙指針

文章目錄題目描述思路注意代碼實現題目描述 請實現一個函數&#xff0c;把字符串 s 中的每個空格替換成"%20"。 示例 1&#xff1a; 輸入&#xff1a;s “We are happy.” 輸出&#xff1a;“We%20are%20happy.” 限制&#xff1a; 0 < s 的長度 < 10000 思…

Springmvc,Spring MVC文件上傳

Springmvc文件上傳&#xff1a; 1.代碼截圖如下&#xff1a; 2.UploadController.java: package cn.csdn.controller;import java.io.File;import javax.servlet.http.HttpServletRequest;import org.springframework.stereotype.Controller; import org.springframework.ui.…

倒序輸出鏈表

文章目錄題目描述思路遞歸法棧題目描述 輸入一個鏈表的頭節點&#xff0c;從尾到頭反過來返回每個節點的值&#xff08;用數組返回&#xff09;。 示例 1&#xff1a; 輸入&#xff1a;head [1,3,2] 輸出&#xff1a;[2,3,1] 限制&#xff1a; 0 < 鏈表長度 < 10000 思…

插入迭代器、流迭代器、反向迭代器、移動迭代器

文章目錄前言插入迭代器inserterfront_inserterback_inserteriostream迭代器istream_iterator 讀取輸入流istream_iterator允許使用懶惰求值ostream_iterator操作反向迭代器reverse_iterator的base成員函數前言 除了為每個容器定義的迭代器之外&#xff0c;標準庫在頭文件iter…

泛型算法(lambda表達式、function類模板、bind函數適配器、迭代器類別、鏈表數據結構獨有的算法)

文章目錄概念find()函數迭代器令算法不依賴于容器但算法依賴于元素類型的操作算法永遠不會執行容器的操作只讀算法accumulate()函數從兩個序列中讀取元素&#xff08;equal函數為例&#xff09;迭代器作為參數形成兩個序列equal()寫容器元素的算法概念fill()fill_n()插入迭代器…

jsp,div 限制字數,超出部分用省略號代替

1.我是用struts2標簽做的&#xff1a;如下&#xff1a; <% page language"java" import"java.util.*" pageEncoding"UTF-8"%> <% taglib prefix"s" uri"/struts-tags"%> <%String path request.getContext…

C++之關聯容器

文章目錄概述及類型mapsetpair類型概念初始化默認初始化提供初始化器允許的操作可以創建一個pair類的函數可以作為容器的類型關聯容器迭代器概念map的迭代器set的迭代器是const的初始化map and setmultimap and multiset關聯容器的操作額外的類型別名關聯容器和算法刪除元素添加…

動態內存、智能指針(shared_ptr、unique_ptr、weak_ptr)、動態數組

文章目錄三種對象的分類三種內存的區別動態內存概念智能指針允許的操作智能指針的使用規范new概念內存耗盡/定位new初始化默認初始化直接初始化值初始化delete概念手動釋放動態對象空懸指針shared_ptr類格式獨有的操作make_shared函數shared_ptr的計數器通過new用普通指針初始化…

動態數組的簡單應用

文章目錄連接兩個字符串字面常量題目注意代碼輸出結果處理輸入的變長字符串題目注意代碼連接兩個字符串字面常量 題目 連接兩個字符串字面常量&#xff0c;將結果保存在一個動態分配的char數組中。重寫&#xff0c;連接兩個標準庫string對象。 注意 使用頭文件cstring的str…

二分查找算法實現

文章目錄思路代碼以二分區間作為while判定條件以給定值作為while判定條件主函數思路 while判定條件的選擇&#xff0c;注意最外層的return的內容就好。下面提供了兩個代碼版本。計算 mid 時需要防止溢出&#xff08;對應類型【如本例中的int】可能存不下&#xff09;&#xff…