国产亚洲精品福利在线无卡一,国产精久久一区二区三区,亚洲精品无码国模,精品久久久久久无码专区不卡

當前位置: 首頁 > news >正文

網(wǎng)站開發(fā)如何讓圖片加載的更快第一推廣網(wǎng)

網(wǎng)站開發(fā)如何讓圖片加載的更快,第一推廣網(wǎng),python大型網(wǎng)站開發(fā),山東聊城建設學校網(wǎng)站文章目錄 一、封裝二、項目文件拆分三、構(gòu)造函數(shù)和析構(gòu)函數(shù)1.構(gòu)造函數(shù)的分類及調(diào)用2.拷貝函數(shù)調(diào)用時機3.構(gòu)造函數(shù)調(diào)用規(guī)則4.深拷貝與淺拷貝5.初始化列表6.類對象作為類成員7.靜態(tài)成員 四、C對象模型和this指針1.類的對象大小計算2.this指針3.空指針訪問成員函數(shù)4.const修飾成員…

文章目錄

  • 一、封裝
  • 二、項目文件拆分
  • 三、構(gòu)造函數(shù)和析構(gòu)函數(shù)
    • 1.構(gòu)造函數(shù)的分類及調(diào)用
    • 2.拷貝函數(shù)調(diào)用時機
    • 3.構(gòu)造函數(shù)調(diào)用規(guī)則
    • 4.深拷貝與淺拷貝
    • 5.初始化列表
    • 6.類對象作為類成員
    • 7.靜態(tài)成員
  • 四、C++對象模型和this指針
    • 1.類的對象大小計算
    • 2.this指針
    • 3.空指針訪問成員函數(shù)
    • 4.const修飾成員函數(shù)
  • 五、友元
    • 1.全局函數(shù)做友元
    • 2.類做友元
    • 3.成員函數(shù)做友元

一、封裝

C++面向?qū)ο蟮娜筇匦詾?#xff1a;封裝、繼承、多態(tài)。
C++認為萬事萬物皆為對象,對象都有其屬性和行為。比如人作為對象,屬性有姓名、年齡、身高、體重、性別等,行為有走、跑、跳等。
具有相同性質(zhì)的對象,可以抽象稱為類。
封裝是C++面向?qū)ο蟮娜筇匦灾?#xff0c;封裝的意義是將屬性和行為作為一個整體表現(xiàn)對象或事務,同時將屬性和行為加以權(quán)限控制。
類中的屬性和行為統(tǒng)一稱為成員。類中的屬性稱為成員屬性或者成員變量,類中的行為稱為成員函數(shù)或成員方法。
訪問的權(quán)限有三種,公共權(quán)限(public)、保護權(quán)限(protected)和私有權(quán)限(private)。
公共權(quán)限類內(nèi)可以訪問,類外也可以訪問;保護權(quán)限和私有權(quán)限類內(nèi)可以訪問,類外不可以訪問。保護權(quán)限和私有權(quán)限的區(qū)別在繼承時有所體現(xiàn),子類可以訪問父類保護權(quán)限下的屬性和行為,但是子類不可以訪問父類私有權(quán)限下的屬性和行為。
類的默認權(quán)限是私有權(quán)限(private)。結(jié)構(gòu)體的默認權(quán)限是公共。
下面代碼就是一個創(chuàng)建類并實例化類的的例子。

#include <iostream>
using namespace std;
#define PI 3.14//圓類
class Circle
{//訪問權(quán)限
public:   //公共權(quán)限//屬性  一般就是變量int radius;//行為  一般用函數(shù)來實現(xiàn)double perimeter(){return 2*PI*radius;}double area(){return PI*radius*radius;}
};int main()
{//通過圓類創(chuàng)建一個具體的圓對象——實例化Circle c1,c2;//給圓對象的屬性賦值c1.radius = 1;c2.radius = 10;cout<<"半徑為"<<c1.radius<<"的圓的周長為:"<<c1.perimeter()<<endl;cout<<"半徑為"<<c2.radius<<"的圓的面積為:"<<c2.area()<<endl;system("pause");return 0;
}

上面程序的運行結(jié)果如下圖所示。
在這里插入圖片描述
創(chuàng)建一個學生類,設置姓名、學號屬性,顯示學生信息的行為,姓名和學號可以由用戶輸入,示例如下。
在這里插入圖片描述
在類中也可以通過行為為屬性賦值。

#include <iostream>
#include <string>
using namespace std;class Student
{
public:string name;string num;void show(){cout<<"姓名:"<<name<<" 學號:"<<num<<endl;}void set_name(string s_name,string s_num){name = s_name;num = s_num;}
};int main()
{Student s;s.set_name("Jones","20240105");cout<<"學生信息"<<endl;s.show();system("pause");return 0;
}

在設計類的時候,可以把屬性和行為放在不同的權(quán)限下加以控制。
如果在主函數(shù)中訪問保護權(quán)限或私有權(quán)限下的屬性,代碼中會直接報錯。
在這里插入圖片描述
將類中成員的屬性設置為私有,然后通過在類中寫一些公共權(quán)限的行為來控制讀寫權(quán)限。

#include <iostream>
#include <string>
using namespace std;class Person
{
public:void setAttribute(string s,int a,int b){name = s;age = a;password = b;}string getName(){return name;}int getAge(){return age;}int getPassword(){return password;}private:string name;   //可讀可寫int age;int password;
};int main()
{Person p;p.setAttribute("Jones",20,123456);cout<<"姓名:"<<p.getName()<<endl;cout<<"年齡:"<<p.getAge()<<endl;cout<<"密碼:"<<p.getPassword()<<endl;system("pause");return 0;
}

雖然上面代碼中的屬性不能再main函數(shù)中直接訪問修改,但是可以通過調(diào)用類中的公有方法來修改或者讀取其屬性。
立方體的案例
下面代碼中設計了一個立方體類,然后通過成員函數(shù)求立方體的面積和體積,并分別利用全局函數(shù)和成員函數(shù)判斷兩個立方體是否相同。

#include <iostream>
#include <string>
using namespace std;class Cube
{
public:void set_attr(double a,double b,double c){c_l = a;c_w = b;c_h = c;}double get_length(){return c_l;}double get_wide(){return c_w;}double get_height(){return c_h;}double cube_area(){return 2*(c_l*c_w+c_l*c_h+c_w*c_h);}double cube_volume(){return c_l*c_w*c_h;}//利用全局函數(shù)判斷兩個立方體是否相同bool isSame(Cube &a)  //成員函數(shù)可以與全局函數(shù)同名{if(a.get_length()== c_l && a.get_wide()==c_w && a.get_height()==c_h)return true;return false;}
private:double c_l;double c_w;double c_h;
};//利用全局函數(shù)判斷兩個立方體是否相同
bool isSame(Cube &a,Cube &b)
{if(a.get_length()==b.get_length() && a.get_wide()==b.get_wide() && a.get_height()==b.get_height())return true;return false;
}int main()
{Cube c1,c2;c1.set_attr(10,10,10);cout<<"立方體的面積:"<<c1.cube_area()<<endl;cout<<"立方體的體積:"<<c1.cube_volume()<<endl;c2.set_attr(10,10,10);//利用全局函數(shù)判斷if(isSame(c1,c2))cout<<"1.兩個立方體相同!"<<endl;elsecout<<"1.兩個立方體不相同!"<<endl;//利用成員方法判斷if(c1.isSame(c2))cout<<"2.兩個立方體相同!"<<endl;elsecout<<"2.兩個立方體不相同!"<<endl;system("pause");return 0;
}

程序運行結(jié)果如下圖所示。
在這里插入圖片描述
判斷點和圓關(guān)系的案例 ——在類中可以讓另一個類作為本類的成員。
點和圓的關(guān)系有三種:點在圓外、點在圓上、點在圓內(nèi)。
下面代碼完成的就是點和圓位置關(guān)系的判斷。

#include <iostream>
#include <string>
using namespace std;class Point
{
public://設置坐標void set_xy(int a,int b){x = a;y = b;}int get_x(){return x;}int get_y(){return y;}
private:int x;int y;
};class Circle
{
public://設置半徑void set_r(int a){radius = a;}int get_r(){return radius;}//設置圓心void set_center(Point p){center = p;}Point get_center(){return center;}
private:int radius;  //半徑Point center;  //圓心
};//判斷點與圓的關(guān)系
void point_circle(Circle &c,Point &p)
{int x,y,r;r = c.get_r();x = p.get_x()-c.get_center().get_x();y = p.get_y()-c.get_center().get_y();if(x*x+y*y > r*r)cout<<"點在圓外!"<<endl;else if(x*x+y*y < r*r)cout<<"點在圓內(nèi)!"<<endl;elsecout<<"點在圓上!"<<endl;
}int main()
{Point p1,p2;p1.set_xy(0,0);p2.set_xy(1,1);Circle c;c.set_center(p1);c.set_r(1);point_circle(c,p2);system("pause");return 0;
}

二、項目文件拆分

項目文件拆分的作用可以使得功能更加清楚。
將上面判斷點和圓關(guān)系的案例代碼中的類都獨立的寫到頭文件和各自的C++文件中實現(xiàn)。
項目中包含圓類和點類的頭文件,源文件中有圓類方法的實現(xiàn)、點類方法的實現(xiàn)文件以及包含主函數(shù)的文件。
在這里插入圖片描述
point.h文件中只做變量和函數(shù)的聲明,不做函數(shù)實現(xiàn)。

#pragma once  //防止頭文件重復包含
#include <iostream>
using namespace std;//在頭文件只做變量和函數(shù)的聲明,不做函數(shù)實現(xiàn)
class Point
{
public://設置坐標void set_xy(int a,int b);int get_x();int get_y();
private:int x;int y;
};

點類中成員函數(shù)的實現(xiàn)放在point.cpp文件中,不過要在每個函數(shù)前面加上作用域。

#include "point.h"   //包含對應的頭文件//在C++文件做成員函數(shù)實現(xiàn)
void Point::set_xy(int a,int b)  //需要告知成員函數(shù)的作用域 Point::
{x = a;y = b;
}
int Point::get_x()
{return x;
}
int Point::get_y()
{return y;
}

同樣地,circle.h文件中只做變量和函數(shù)的聲明,不做函數(shù)實現(xiàn),且Circle類用到了Point類,需要將點類的頭文件包含進來。

#pragma once  //防止頭文件重復包含
#include <iostream>
#include "point.h"
using namespace std;//在頭文件只做變量和函數(shù)的聲明,不做函數(shù)實現(xiàn)
class Circle
{
public://設置半徑void set_r(int a);int get_r();//設置圓心void set_center(Point p);Point get_center();
private:int radius;  //半徑Point center;  //圓心
};

圓類中成員函數(shù)的實現(xiàn)放在circle.cpp文件中,同樣要在每個函數(shù)前面加上作用域。

#include "circle.h"   //包含對應的頭文件//在C++文件做成員函數(shù)實現(xiàn)
//設置半徑
void Circle::set_r(int a)  //需要告知成員函數(shù)的作用域 Circle::
{radius = a;
}
int Circle::get_r()
{return radius;
}
//設置圓心
void Circle::set_center(Point p)
{center = p;
}
Point Circle::get_center()
{return center;
}

main.cpp文件中需要包含上面的兩個頭文件,然后在主函數(shù)中進行函數(shù)調(diào)用即可完成相應的功能。

#include <iostream>
#include <string>
#include "point.h"
#include "circle.h"
using namespace std;//判斷點與圓的關(guān)系
void point_circle(Circle &c,Point &p)
{int x,y,r;r = c.get_r();x = p.get_x()-c.get_center().get_x();y = p.get_y()-c.get_center().get_y();if(x*x+y*y > r*r)cout<<"點在圓外!"<<endl;else if(x*x+y*y < r*r)cout<<"點在圓內(nèi)!"<<endl;elsecout<<"點在圓上!"<<endl;
}int main()
{Point p1,p2;p1.set_xy(0,0);p2.set_xy(1,1);Circle c;c.set_center(p1);c.set_r(1);point_circle(c,p2);system("pause");return 0;
}

三、構(gòu)造函數(shù)和析構(gòu)函數(shù)

C++中的每個對象都會有初始設置以及對象銷毀前的數(shù)據(jù)清理。
對象的初始化和清理是兩個非常重要的安全問題。一個對象或者變量沒有初始狀態(tài),對其使用后果是未知;使用完一個對象或者變量,沒有及時清理的話,也會造成一定的安全問題。
C++利用了構(gòu)造函數(shù)和析構(gòu)函數(shù)分別解決初始化和清理問題,這兩個函數(shù)將會被編譯器自動調(diào)用,完成對象的初始化和清理工作。 對象的初始化和清理工作是編譯器強制做的事情,如果我們不提供構(gòu)造函數(shù)和析構(gòu)函數(shù),編譯器會執(zhí)行編譯器提供的構(gòu)造函數(shù)和析構(gòu)函數(shù),不過都是空實現(xiàn)。
構(gòu)造函數(shù):創(chuàng)建對象時為對象的成員屬性賦值,由編譯器自動調(diào)用,無須手動調(diào)用。
析構(gòu)函數(shù):對象銷毀前系統(tǒng)自動調(diào)用,執(zhí)行清理工作。
構(gòu)造函數(shù)語法:類名(){}
構(gòu)造函數(shù)沒有返回值,也不用寫void;函數(shù)名稱與類名相同;構(gòu)造函數(shù)可以有參數(shù),可以發(fā)生函數(shù)重載;程序在調(diào)用對象的時候會自動調(diào)用構(gòu)造函數(shù),而且只調(diào)用一次,無須手動調(diào)用。
析構(gòu)函數(shù)語法:~類名(){}
析構(gòu)函數(shù)沒有返回值,也不用寫void;函數(shù)名稱與類名相同,不過要在類名前面加上~符號;析構(gòu)函數(shù)不可以有參數(shù),因此不可以發(fā)生函數(shù)重載;程序在對象銷毀前會自動調(diào)用析構(gòu)函數(shù),而且只調(diào)用一次,無須手動調(diào)用。

#include <iostream>
#include <string>
using namespace std;class Person
{
public://構(gòu)造函數(shù)Person(){cout<<"Person構(gòu)造函數(shù)調(diào)用!"<<endl;}//析構(gòu)函數(shù)~Person(){cout<<"Person析構(gòu)函數(shù)調(diào)用!"<<endl;}
};void fun()
{Person p;  //存放在棧區(qū),函數(shù)執(zhí)行完以后會釋放空間,因此會調(diào)用析構(gòu)函數(shù)
}int main()
{fun();system("pause");return 0;
}

上面代碼運行后的結(jié)果如下圖所示,雖然只是在函數(shù)中實例化了一個Person類對象,但是構(gòu)造函數(shù)和析構(gòu)函數(shù)都執(zhí)行了。
在這里插入圖片描述
如果不是通過函數(shù)實例化對象,而是將函數(shù)中的代碼直接放在主函數(shù)中,析構(gòu)函數(shù)輸出的內(nèi)容需要按下任意鍵后才會執(zhí)行。

1.構(gòu)造函數(shù)的分類及調(diào)用

構(gòu)造函數(shù)按照參數(shù)的有無分為有參構(gòu)造和無參構(gòu)造,無參構(gòu)造也稱默認構(gòu)造;按類型分為普通構(gòu)造和拷貝構(gòu)造。
構(gòu)造函數(shù)的調(diào)用方式:括號法、顯示法、隱式轉(zhuǎn)換法。

#include <iostream>
#include <string>
using namespace std;class Person
{
public://構(gòu)造函數(shù)Person(){cout<<"Person無參構(gòu)造函數(shù)調(diào)用!"<<endl;}Person(int a){age = a;cout<<"Person有參構(gòu)造函數(shù)調(diào)用!"<<endl;}Person(const Person &p)  //不能改變原有類的屬性,要用const{age = p.age;  //將參數(shù)中的所有屬性加以拷貝cout<<"Person拷貝構(gòu)造函數(shù)調(diào)用!"<<endl;}//析構(gòu)函數(shù)~Person(){cout<<"Person析構(gòu)函數(shù)調(diào)用!"<<endl;}
public:int age;
};void fun()
{//1.括號法調(diào)用構(gòu)造函數(shù)Person p1;   //默認(無參)構(gòu)造函數(shù)的調(diào)用 //Person p1();   不能實現(xiàn)無參構(gòu)造函數(shù)的調(diào)用,編譯器會認為這是函數(shù)聲明Person p2(20);   //有參構(gòu)造函數(shù)的調(diào)用Person p3(p2);   //拷貝構(gòu)造函數(shù)的調(diào)用cout<<"p2年齡:"<<p2.age<<endl;cout<<"p3年齡:"<<p3.age<<endl;//2.顯式法調(diào)用構(gòu)造函數(shù)Person p4 = Person(20);   //Person(20)單獨成行叫做匿名對象,執(zhí)行該行后系統(tǒng)會回收掉匿名對象Person p5 = Person(p4);   //匿名對象前有等號,其就不是匿名對象了//Person(p4);   //不要利用拷貝函數(shù)初始化匿名對象,這行等價于 Person p2; 其已經(jīng)定義過了//3.隱式法調(diào)用構(gòu)造函數(shù)Person p6 = 20;   //編譯器會將其轉(zhuǎn)換為  Person p6 = Person(20);Person p7 = p6;
}int main()
{fun();system("pause");return 0;
}

下面的構(gòu)造函數(shù)調(diào)用方式不能實現(xiàn)無參構(gòu)造函數(shù)的調(diào)用,編譯器會認為這是函數(shù)聲明。

Person p1();   

Person(20)單獨在一行叫做匿名對象,執(zhí)行完該行后系統(tǒng)會立即回收掉匿名對象。

Person(20); 

對于匿名對象,函數(shù)執(zhí)行完匿名對象這行后,立即調(diào)用了析構(gòu)函數(shù)回收清理,然后才執(zhí)行后面的打印行。
在這里插入圖片描述
不要利用拷貝函數(shù)初始化匿名對象,其效果相當于自動去掉括號,會發(fā)生重定義錯誤。

Person(p1);

2.拷貝函數(shù)調(diào)用時機

拷貝函數(shù)調(diào)用時機:使用一個已經(jīng)創(chuàng)建完畢的對象來初始化一個新對象;值傳遞的方式給函數(shù)傳值;值方式返回局部對象。
1.使用一個已經(jīng)創(chuàng)建完畢的對象來初始化一個新對象。

Person p1(20);  //有參構(gòu)造函數(shù)調(diào)用
Person p2(p1);  //拷貝構(gòu)造函數(shù)調(diào)用
//拷貝完成后對一個對象屬性的修改不會影響到另一個對象

2.值傳遞的方式給函數(shù)傳值這種情況下,函數(shù)形參這里會進行拷貝函數(shù)的調(diào)用。

void fun(Person p)
{...
}int main()
{Person p;fun(p);...
}

3.值方式返回局部對象

Person fun()
{Person p;return p;  //返回的局部變量是一份拷貝
}int main()
{Person p = fun(p);...
}

3.構(gòu)造函數(shù)調(diào)用規(guī)則

默認情況下,C++編譯器至少給一個類添加3個函數(shù):默認構(gòu)造函數(shù)(空實現(xiàn))、默認析構(gòu)函數(shù)(空實現(xiàn))、默認拷貝函數(shù)(值拷貝)。
構(gòu)造函數(shù)調(diào)用規(guī)則:如果用戶定義了有參構(gòu)造函數(shù),C++不再提供無參構(gòu)造函數(shù),但會提供默認拷貝函數(shù);如果用戶定義了拷貝構(gòu)造函數(shù),C++不會再提供其他的構(gòu)造函數(shù)。
按照無參構(gòu)造函數(shù)、有參構(gòu)造函數(shù)、拷貝構(gòu)造函數(shù)由前及后的順序,若定義了前邊的構(gòu)造函數(shù),后面的構(gòu)造函數(shù)編譯器仍然提供,若定義了后面的構(gòu)造函數(shù),前面的構(gòu)造函數(shù)編譯器便不再提供,需要使用的話就要自己定義實現(xiàn)。
下面的代碼中沒有寫拷貝構(gòu)造函數(shù),但是在函數(shù)體中調(diào)用了拷貝構(gòu)造函數(shù)。

#include <iostream>
#include <string>
using namespace std;class Person
{
public://構(gòu)造函數(shù)Person(){cout<<"Person無參構(gòu)造函數(shù)調(diào)用!"<<endl;}Person(int a){age = a;cout<<"Person有參構(gòu)造函數(shù)調(diào)用!"<<endl;}//析構(gòu)函數(shù)~Person(){cout<<"Person析構(gòu)函數(shù)調(diào)用!"<<endl;}
public:int age;
};void fun()
{Person p1(20);  //有參構(gòu)造函數(shù)調(diào)用Person p2(p1);  //拷貝構(gòu)造函數(shù)調(diào)用cout<<"p1的年齡:"<<p1.age<<endl;cout<<"p2的年齡:"<<p2.age<<endl;
}int main()
{fun();system("pause");return 0;
}

代碼的執(zhí)行結(jié)果如下圖所示。
在這里插入圖片描述

4.深拷貝與淺拷貝

淺拷貝就是簡單的賦值拷貝操作。
深拷貝是在堆區(qū)重新申請空間進行拷貝的操作。
如果屬性有在堆區(qū)開辟的,一定要自己提供拷貝構(gòu)造函數(shù),防止淺拷貝帶來的問題。
下面這段程序?qū)崿F(xiàn)的就是淺拷貝,默認拷貝函數(shù)中的內(nèi)容就是下面寫的這樣,將屬性逐一復制。在析構(gòu)函數(shù)中對構(gòu)造函數(shù)中申請的堆區(qū)內(nèi)存進行了釋放,fun()函數(shù)中先后實例化了p1和p2兩個對象,p2對象后入棧,所以先執(zhí)行析構(gòu)函數(shù)對堆區(qū)內(nèi)存進行釋放,這里不會出問題。當p1對象執(zhí)行析構(gòu)函數(shù)的時候,成員變量height的值是非空的,但是申請的堆區(qū)內(nèi)存已經(jīng)被p2釋放掉了,這個時候程序就會出現(xiàn)問題。

#include <iostream>
#include <string>
using namespace std;class Person
{
public://構(gòu)造函數(shù)Person(){cout<<"Person無參構(gòu)造函數(shù)調(diào)用!"<<endl;}Person(int a,int b){age = a;height = new int(b);cout<<"Person有參構(gòu)造函數(shù)調(diào)用!"<<endl;}//拷貝構(gòu)造函數(shù)Person(const Person &p){//默認的拷貝構(gòu)造函數(shù)將屬性逐一復制age = p.age;//height = p.height;  //淺拷貝height = new int(*p.height);  //深拷貝cout<<"Person拷貝構(gòu)造函數(shù)調(diào)用!"<<endl;}//析構(gòu)函數(shù)~Person(){if(height != NULL){delete height;height = NULL;}cout<<"Person析構(gòu)函數(shù)調(diào)用!"<<endl;}
public:int age;int *height;
};void fun()
{Person p1(20,175);  //有參構(gòu)造函數(shù)調(diào)用cout<<"p1的年齡:"<<p1.age<<" p1的身高:"<<*p1.height<<endl;Person p2(p1);  //有參構(gòu)造函數(shù)調(diào)用cout<<"p2的年齡:"<<p2.age<<" p2的身高:"<<*p2.height<<endl;
}int main()
{fun();system("pause");return 0;
}

深拷貝的實現(xiàn)也很簡單,把拷貝構(gòu)造函數(shù)中涉及堆區(qū)內(nèi)存變量拷貝的,獨自申請一塊堆區(qū)內(nèi)存來接收,這樣一來,雖然拷貝后指針指向的位置不再與原來的地址相同,但是里面存放的值是一樣的。
對于淺拷貝而言,不寫拷貝構(gòu)造函數(shù)也是可以的,采用默認的拷貝構(gòu)造函數(shù),但是對于深拷貝來說,拷貝構(gòu)造函數(shù)中需要重新申請堆區(qū)內(nèi)存存放值。

Person(const Person &p)
{//默認的拷貝構(gòu)造函數(shù)將屬性逐一復制age = p.age;//height = p.height;  //淺拷貝height = new int(*p.height);  //深拷貝cout<<"Person拷貝構(gòu)造函數(shù)調(diào)用!"<<endl;
}

改為深拷貝后,程序的運行結(jié)果如下圖所示。
在這里插入圖片描述

5.初始化列表

初始化列表賦值的語法:構(gòu)造函數(shù)(): 屬性1(值1),屬性2(值2), …,屬性n(值n){}
也可以在構(gòu)造函數(shù)中加入?yún)?shù),并將參數(shù)值一一賦給屬性值,這樣在賦值時更加靈活,比如:構(gòu)造函數(shù)(int a, int b): 屬性1(a),屬性2(b){}

#include <iostream>
#include <string>
using namespace std;class Person
{
public://傳統(tǒng)方式賦值Person(int a,int b){x = a;y = b;}//初始化列表方式賦值Person():x(10),y(20){}public:int x;int y;
};void fun()
{Person p1;  //初始化列表方式賦值Person p2(11,22);  //傳統(tǒng)方式賦值cout<<"1.a="<<p1.x<<" b="<<p1.y<<endl;cout<<"2.a="<<p2.x<<" b="<<p2.y<<endl;
}int main()
{fun();system("pause");return 0;
}

6.類對象作為類成員

C++類中的成員可以是另一個類的對象,稱該成員為對象成員。
當其他類對象作為本類的成員時,構(gòu)造的時候先構(gòu)造類對象,然后再構(gòu)造自身。
比如下面的例子,B類中有對象A作為成員,A為對象成員。構(gòu)造時先執(zhí)行A的構(gòu)造函數(shù),再執(zhí)行B的構(gòu)造函數(shù)。

class A
{...
}
class B
{A a;
}

構(gòu)造時先構(gòu)造類對象,再構(gòu)造自身;析構(gòu)的時候先析構(gòu)自身,再析構(gòu)類對象。

#include <iostream>
#include <string>
using namespace std;class Phone
{
public:Phone(string s){name = s;cout<<"Phone的構(gòu)造函數(shù)!"<<endl;}~Phone(){cout<<"Phone的析構(gòu)函數(shù)!"<<endl;}string name;
};class Person
{
public:Person(string s1,string s2):name(s1),brand(s2){cout<<"Person的構(gòu)造函數(shù)!"<<endl;}~Person(){cout<<"Person的析構(gòu)函數(shù)!"<<endl;}public:string name;Phone brand;
};void fun()
{Person p("Jones","iphone"); cout <<p.name<<"手機牌子是"<<p.brand.name<<endl;
}int main()
{fun();system("pause");return 0;
}

上面代碼執(zhí)行后的結(jié)果如下圖所示。
在這里插入圖片描述

7.靜態(tài)成員

靜態(tài)成員就是在成員變量或者成員函數(shù)前加關(guān)鍵字static。靜態(tài)成員分為靜態(tài)成員變量和靜態(tài)成員函數(shù)。
靜態(tài)成員變量特點:所有對象共享同一份數(shù)據(jù),一個對象修改值后,其他對象訪問到的就是修改后的新值;在編譯階段分配內(nèi)存;靜態(tài)成員變量在類內(nèi)聲明,類外初始化,初始化的時候要加作用域。
靜態(tài)成員變量可以通過類名直接訪問,其也有訪問權(quán)限。

#include <iostream>
#include <string>
using namespace std;class Person
{
public:static int a;  //類內(nèi)聲明
};int Person::a = 10;  //類外初始化,要加作用域,否則就是全局變量void fun()
{Person p1; cout <<"1.a="<<p1.a<<endl;Person p2; p2.a = 20;cout <<"2.a="<<p1.a<<endl;  //所有對象共享一份數(shù)據(jù)cout <<"3.a="<<Person::a<<endl;  //通過類名直接訪問靜態(tài)變量
}int main()
{fun();system("pause");return 0;
}

上面代碼運行后的結(jié)果如下圖所示。
在這里插入圖片描述
靜態(tài)成員函數(shù)特點:所有對象共享同一個函數(shù);靜態(tài)成員函數(shù)只能訪問靜態(tài)成員變量,不可以訪問非靜態(tài)成員變量,非靜態(tài)成員變量必須與特定的對象相對。
靜態(tài)成員函數(shù)可以通過對象訪問,也可以通過類名訪問。

#include <iostream>
#include <string>
using namespace std;class Person
{
public:static int a;  //類內(nèi)聲明static void fun(){a = 100;cout <<"靜態(tài)成員函數(shù)的調(diào)用!"<<endl;}
};int Person::a = 10;  //類外初始化,要加作用域,否則就是全局變量int main()
{Person p;cout <<"1.a="<<Person::a<<endl;p.fun();cout <<"2.a="<<Person::a<<endl;Person::fun();system("pause");return 0;
}

上面代碼運行后的結(jié)果如下圖所示。
在這里插入圖片描述


四、C++對象模型和this指針

1.類的對象大小計算

在C++中,類內(nèi)的成員變量和成員函數(shù)分開存儲,只有非靜態(tài)成員變量才屬于類的對象上。
空對象占用的內(nèi)存空間為1個字節(jié)大小。
C++編譯器會為每個空對象分配一個字節(jié)的空間,這是為了區(qū)分不同對象占用內(nèi)存的位置,比如聲明兩個空對象,不能讓它們指向同一塊內(nèi)存空間,每個對象應該有一塊獨一無二的空間,即使它是空的。
在這里插入圖片描述
只有非靜態(tài)成員變量的大小才算在類的對象上,靜態(tài)變量、靜態(tài)函數(shù)、函數(shù)都不算字節(jié)空間。
在這里插入圖片描述
對象也存在字節(jié)對齊。
在這里插入圖片描述

2.this指針

C++提供特殊的對象指針——this指針,this指針指向被調(diào)用的成員函數(shù)所屬的對象。
this指針是隱含在每一個非靜態(tài)成員函數(shù)內(nèi)的一種指針,其不需要定義,直接使用。
this指針的用途:當形參和成員變量同名的時候,可以用this指針來進行區(qū)分,解決名稱沖突;在類的非靜態(tài)成員函數(shù)中返回對象本身,可以使用return *this。
this指針解決名稱沖突的例子如下圖所示。
在這里插入圖片描述
在類的非靜態(tài)成員函數(shù)中返回對象本身的例子如下。

#include <iostream>
#include <string>
using namespace std;class Person
{
public:Person(int age){this->age = age;}Person& Addage(Person &p)  //以引用的方式返回{this->age += p.age;return *this;  //返回對象本身}int age;
};int main()
{Person p1(10);Person p2(20);p2.Addage(p1).Addage(p1).Addage(p1);  //鏈式編程的思想cout <<"age="<<p1.age<<endl;cout <<"age="<<p2.age<<endl;system("pause");return 0;
}

因為成員函數(shù)返回的是對象本身,因此可以連續(xù)調(diào)用成員函數(shù),這就是鏈式編程思想的體現(xiàn)。
上面代碼的運行結(jié)果如下圖所示。
在這里插入圖片描述

3.空指針訪問成員函數(shù)

空指針訪問成員變量的時候就會報錯,因為類中成員變量前默認有一個this指針,如果指針是空的,自然是訪問不到,因此為了程序的健壯性,應當在訪問之前先判斷所傳的指針是否為空再進行下一步操作。

#include <iostream>
#include <string>
using namespace std;class Person
{
public:void show_name(){cout <<"class name : Person"<<endl;}void show_age(){if(this == NULL)return;cout <<"age="<<age<<endl; //與下一行代碼是一樣的//cout <<"age="<<this->age<<endl;}int age;
};int main()
{Person *p = NULL;p->show_name();p->show_age();system("pause");return 0;
}

4.const修飾成員函數(shù)

成員函數(shù)后加const稱為常函數(shù),常函數(shù)內(nèi)不可以修改成員屬性。 成員屬性聲明時加關(guān)鍵字mutable后,在常函數(shù)中仍然可以修改。
聲明對象前加const稱為常對象,常對象只能調(diào)用常函數(shù). 因為普通函數(shù)中有可能對成員屬性作修改,如果調(diào)用相當于變向的修改了屬性。成員屬性聲明時加關(guān)鍵字mutable后,通過常對象訪問可以修改。

class Person
{
public://this指針的本質(zhì)是指針常量,指針的指向不可以修改,但是值是可以修改的//this指針相當于Person * const thisvoid show_age1(){this->age = 10;   //可以修改}//此時this指針再被const修飾,相當于const Person * const this,指針的指向和值都不可以被修改void show_age2() const{this->age = 20;   //不可以修改m_age = 20;   //可以修改}int age;mutable int m_age;
};const Person p;
p.age = 10;   //不可以修改
p.m_age = 20;  //可以修改

五、友元

友元的目的是讓一個函數(shù)或類訪問另一個類中的私有成員(private)。
友元的關(guān)鍵字是friend。
友元的實現(xiàn):全局函數(shù)做友元;類做友元;成員函數(shù)做友元。

1.全局函數(shù)做友元

全局函數(shù)做友元的代碼如下。

#include <iostream>
#include <string>
using namespace std;class Room
{//全局函數(shù)是友元,可以訪問類中的私有成員friend void fun(Room &r); 
public:Room(){sitting_room = "sitting room";bedroom = "bedroom";}
public:string sitting_room;
private:string bedroom;
};//全局函數(shù)
void fun(Room &r)
{cout<<"Room name:"<<r.sitting_room<<endl;cout<<"Room name:"<<r.bedroom<<endl;  //全局函數(shù)以友元的方式才能訪問類中私有成員
}int main()
{Room room;fun(room);system("pause");return 0;
}

2.類做友元

可以將類中的成員函數(shù)寫在類外,不過要在其前面加上作用域,而且在類中要先聲明該函數(shù)。
類做友元的代碼如下。

#include <iostream>
#include <string>
using namespace std;class Room;
class Person
{
public:Person();void visit();
private:Room *room;
};class Room
{//以類做友元friend class Person;
public:Room();string sitting_room;
private:string bedroom;
};//類外寫構(gòu)造函數(shù),需要說明類作用域
Room::Room()
{sitting_room = "sitting room";bedroom = "bedroom";
}Person::Person()
{//在堆上開辟內(nèi)存room = new Room;
}void Person::visit()
{cout<<"Room name:"<<room->sitting_room<<endl;cout<<"Room name:"<<room->bedroom<<endl;
}int main()
{Person p;p.visit();system("pause");return 0;
}

3.成員函數(shù)做友元

成員函數(shù)做友元的代碼如下。

#include <iostream>
#include <string>
using namespace std;class Room;
class Person
{
public:Person();void visit();
private:Room *room;
};class Room
{//以類中成員函數(shù)做友元friend void Person::visit();
public:Room();string sitting_room;
private:string bedroom;
};//類外寫構(gòu)造函數(shù),需要說明類作用域
Room::Room()
{sitting_room = "sitting room";bedroom = "bedroom";
}Person::Person()
{//在堆上開辟內(nèi)存room = new Room;
}void Person::visit()
{cout<<"Room name:"<<room->sitting_room<<endl;cout<<"Room name:"<<room->bedroom<<endl;
}int main()
{Person p;p.visit();system("pause");return 0;
}

上面三個程序的運行結(jié)果相同,如下圖所示。
在這里插入圖片描述


本文參考視頻:
黑馬程序員匠心之作|C++教程從0到1入門編程,學習編程不再難

http://m.aloenet.com.cn/news/41404.html

相關(guān)文章:

  • 做網(wǎng)站對客戶有什么幫助外包網(wǎng)絡推廣公司
  • wap網(wǎng)站適配競價托管外包
  • 微信小程序是免費的嗎seo工程師是什么職業(yè)
  • 怎么用網(wǎng)站后臺做輪播圖打開百度網(wǎng)站
  • 廣州哪家做網(wǎng)站價格好百度熱搜榜排名
  • 六安網(wǎng)站推廣獲客app第一接單網(wǎng)app地推和拉新
  • wex5 wordpressseo整站優(yōu)化公司持續(xù)監(jiān)控
  • 專業(yè)網(wǎng)站設計服務seo關(guān)鍵字優(yōu)化軟件
  • 企業(yè)網(wǎng)站做seo輿情報告范文
  • 寧波北侖網(wǎng)站建設上海seo外包
  • 建網(wǎng)站域名注冊后需要網(wǎng)絡營銷所學課程
  • 專業(yè)做域名的網(wǎng)站線上營銷平臺
  • 張家港網(wǎng)站建設門店推廣下載app賺錢
  • 武漢企業(yè)做網(wǎng)站找哪家好收錄排名好的發(fā)帖網(wǎng)站
  • 清河做網(wǎng)站哪家好怎么請專業(yè)拓客團隊
  • 網(wǎng)站開發(fā)員鄭州seo培訓班
  • 做網(wǎng)站哪家公司比較好網(wǎng)站流量排行
  • 武漢做商城網(wǎng)站建設寧波seo排名優(yōu)化哪家好
  • 廣州網(wǎng)站關(guān)鍵詞排名鄭州網(wǎng)站關(guān)鍵詞排名技術(shù)代理
  • 緊抓政府網(wǎng)站集約化建設免費網(wǎng)站注冊com
  • dede古典網(wǎng)站模板什么關(guān)鍵詞能搜到資源
  • 怎樣做網(wǎng)站首頁圖片變換網(wǎng)店營銷策劃方案
  • 上海 網(wǎng)站建設 500強關(guān)鍵詞搜索優(yōu)化外包
  • 電商網(wǎng)站怎么制作全國seo公司排名
  • WordPress插件集成在主題青島seo建站
  • 景區(qū)電子商務網(wǎng)站建設免費推廣的網(wǎng)站平臺
  • 佛山專業(yè)網(wǎng)站建設公司哪家好網(wǎng)站廣告投放收費標準
  • 怎么做電視臺網(wǎng)站網(wǎng)站外鏈購買
  • 常州做集裝箱的公司東莞seo網(wǎng)絡推廣專
  • 響應云網(wǎng)站模板下載天津seo優(yōu)化公司哪家好