C++核心程式設計---4.1 類和對象-封裝【P99~P105】
- 4 類和對象
-
- 4.1 類和對象-封裝
-
- 4.1.1 屬性和行為作為整體
- 4.1.2 案例-設計學生類
- 4.1.3 封裝-通路權限
- 4.1.4 C++中 class 和 structure 的差別
- 4.1.5 成員屬性私有化
- 4.1.6 設計案例1-立方體類
- 4.1.7 設計案例2-點和圓關系
- 4.1.7(補)類的分檔案編寫
-
- 7.1.7.1 源檔案
- 4.1.7.2 point類
-
- point.h
- point.cpp
- 4.1.7.3 circle類
-
- circle.h
- circle.cpp
4 類和對象
C++面向對象的三大特性:封裝、繼承和多态
C++認為萬事萬物皆為對象,對象上有其屬性和行為
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsIyZuBnL1QDOzMjMwUTMxATMwEjMwIzLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
- 類中的屬性和行為我們統一稱為成員
- 屬性 成員屬性 成員變量
- 行為 成員函數 成員方法
4.1 類和對象-封裝
封裝是C++面向對象三大特性之一
封裝的意義:
- 将屬性和行為作為一個整體,表現生活中的事物
- 将屬性和行為加以權限控制
4.1.1 屬性和行為作為整體
#include<iostream>
using namespace std;
//設計一個圓類,求圓的周長 2 * PI * 半徑
const double PI = 3.14;
//class代表設計一個類,類後面緊跟着的就是類名稱
class Circle
{
//通路權限
public:
//屬性
int m_r;//半徑
//行為:擷取圓的周長
double calculateZC()
{
return 2 * PI * m_r;
}
};
int main()
{
//通過圓類建立一個具體的對象:圓
//執行個體化:通過一個類建立一個對象的過程
Circle c1;
c1.m_r = 10;
cout << "圓的周長為: " << c1.calculateZC() << endl;
system("pause");
return 0;
}
4.1.2 案例-設計學生類
設計一個學生類,屬性有姓名和學号,可以給姓名和學号指派,可以顯示學生的姓名和學号
#include<iostream>
using namespace std;
#include<string>
//class代表設計一個類,類後面緊跟着的就是類名稱
class Student
{
//通路權限
public:
//屬性
string m_Name;//學生姓名
int m_Id;//學生學号
//行為:給姓名和學号指派,顯示學生的姓名和學号
void setName(string name)
{
m_Name = name;
}
void setId(int id)
{
m_Id = id;
}
void showStudent()
{
cout << "姓名: " << m_Name << "學号: " << m_Id << endl;
}
};
int main()
{
//執行個體化:建立一個具體的學生
Student Stu1;
//給Stu1對象進行屬性指派操作
/*Stu1.m_Name = "張三";
Stu1.m_Id = 01;*/
Stu1.setName("張三");
Stu1.setId(01);
//顯示姓名和學号
Stu1.showStudent();
Student Stu2;
//給Stu1對象進行屬性指派操作
Stu2.m_Name = "李四";
Stu2.m_Id = 02;
//顯示姓名和學号
Stu2.showStudent();
system("pause");
return 0;
}
4.1.3 封裝-通路權限
- 公共權限public: 類内類外均可以通路
- 保護權限protected: 類内可以通路,類外不可以通路,在繼承中,兒子可以通路父親中的保護内容
- 私有權限private: 類内可以通路,類外不可以通路,在繼承中,兒子不可以通路父親的私有内容
# include<iostream>
using namespace std;
#include<string>
class Person
{
public:
string m_Name;//姓名
protected:
string m_Car;//汽車
private:
int m_Password;//銀行卡密碼
public:
void func()//不會報錯,因為三個屬性都支援類内通路
{
m_Name = "張三";
m_Car = "别克";
m_Password = 123456;
}
};
int main()
{
Person p1;
p1.m_Name = "李四";
p1.m_Car = "奔馳";//報錯:保護權限的内容在類外無法通路
p1.m_Password = 234567;//報錯:私有權限在類外也是無法通路
system("pause");
return 0;
}
4.1.4 C++中 class 和 structure 的差別
在C++中,struct 和 class 唯一的差別就在于 預設的通路權限不同
差別:
- struct 預設權限為公共
- class 預設權限為私有
# include<iostream>
using namespace std;
#include<string>
class C1
{
int m_A;//預設權限是私有
};
struct C2
{
int m_A;//預設權限是公共
};
int main()
{
C1 c1;
c1.m_A = 100;//報錯
C2 c2;
c2.m_A = 100;//不報錯
system("pause");
return 0;
}
4.1.5 成員屬性私有化
優點1: 将所有成員屬性設定為私有,可以自己控制讀寫權限
優點2: 對于寫權限,可以檢測資料的有效性
通常情況下,如果我們把屬性都設定為了私有,會對外為這些屬性提供一些 public 的接口來對這些屬性進行通路
# include<iostream>
using namespace std;
#include<string>
class Person
{
public:
//寫姓名(設定姓名)
void setName(string name)
{
m_Name = name;
}
//讀姓名(擷取姓名)
string getName()
{
return m_Name;
}
//擷取年齡,隻讀
int getAge()
{
m_Age = 0;//初始化為0歲
return m_Age;
}
//設定情人,隻寫
void setLover(string lover)
{
m_Lover = lover;
}
private:
string m_Name;//姓名 可讀可寫
int m_Age;//年齡 隻讀
string m_Lover;//情人 隻寫
};
int main()
{
Person p;
p.setName("張三");
cout << "姓名為: " << p.getName() << endl;
cout << "年齡為: " << p.getAge() << endl;
p.setLover("倉井");
system("pause");
return 0;
}
4.1.6 設計案例1-立方體類
- 成員屬性:m_L、m_W、m_H
- 成員行為:擷取立方體面積、擷取立方體體積
- 另外,成員屬性私有化後要設定 public 權限通路接口,即設定、擷取立方體的長寬高
# include<iostream>
using namespace std;
#include<string>
//立方體類設計
//1、建立立方體類
//2、設計屬性
//3、設計行為擷取立方體面積和體積
//4、分别利用全局函數和成員函數判斷兩個立方體是否相等
class Cube
{
private:
int m_L;
int m_W;
int m_H;
public:
//通路接口:設定長
void setL(int l)
{
m_L = l;
}
//通路接口:擷取長
int getL()
{
return m_L;
}
//通路接口:設定寬
void setW(int w)
{
m_W = w;
}
//通路接口:擷取寬
int getW()
{
return m_W;
}
//通路接口:設定高
void setH(int h)
{
m_H = h;
}
//通路接口:擷取高
int getH()
{
return m_H;
}
//擷取立方體面積
int calculateS()
{
return 2 * (m_L * m_W + m_L * m_H + m_W * m_H);
}
//擷取立方體體積
int calculateV()
{
return m_L * m_W * m_H;
}
//利用成員函數判斷兩個立方體是否相等
bool isSameByClass(Cube &c)
{
if (m_L == c.getL() && m_W == c.getW() && m_H == c.getH())
return 1;
else
return 0;
}
};
//利用全局函數判斷兩個立方體是否相等
bool isSame(Cube &c1, Cube &c2)
{
if (c1.getL() == c2.getL() && c1.getW() == c2.getW() && c1.getH() == c2.getH())
return 1;
else
return 0;
}
int main()
{
//建立一個立方體的對象
Cube c1;
c1.setL(10);
c1.setW(10);
c1.setH(10);
cout << "c1的面積為: " << c1.calculateS() << endl;
cout << "c1的體積為: " << c1.calculateV() << endl;
Cube c2;
c2.setL(10);
c2.setW(10);
c2.setH(11);
bool req = isSame(c1, c2);
if (req)
{
cout << "c1和c2是相等的" << endl;
}
else
{
cout << "c1和c2是不相等的" << endl;
}
bool res = c1.isSameByClass(c2);
if (res)
{
cout << "成員函數判斷:c1和c2是相等的" << endl;
}
else
{
cout << "成員函數判斷:c1和c2是不相等的" << endl;
}
system("pause");
return 0;
}
4.1.7 設計案例2-點和圓關系
# include<iostream>
using namespace std;
#include<string>
class Point
{
public:
//設定x
void setX(int x)
{
m_X = x;
}
//擷取x
int getX()
{
return m_X;
}
//設定y
void setY(int y)
{
m_Y = y;
}
//擷取y
int getY()
{
return m_Y;
}
private:
int m_X;
int m_Y;
};
class Circle
{
public:
//設定半徑
void setR(int r)
{
m_R = r;
}
//擷取半徑
int getR()
{
return m_R;
}
//設定圓心
void setCenter(Point center)
{
m_Center = center;
}
//擷取圓心
Point getCenter()
{
return m_Center;
}
private:
int m_R;
Point m_Center;//圓心
};
//判斷點和圓關系
void isInCircle(Circle &c,Point &p)
{
//計算兩點之間距離的平方
int distance = (c.getCenter().getX() - p.getX()) * (c.getCenter().getX() - p.getX()) +
(c.getCenter().getY() - p.getY()) * (c.getCenter().getY() - p.getY());
//計算半徑的平方
int rDistance = c.getR() * c.getR();
//判斷關系
if (distance == rDistance)
{
cout << "點在圓上" << endl;
}
else if (distance > rDistance)
{
cout << "點在圓外" << endl;
}
else
{
cout << "點在圓内" << endl;
}
}
int main()
{
//建立圓
Circle c;
c.setR(10);
Point center;
center.setX(10);
center.setY(0);
c.setCenter(center);
//建立點
Point p;
p.setX(10);
p.setY(11);
//比較
isInCircle(c, p);
system("pause");
return 0;
}
4.1.7(補)類的分檔案編寫
這樣就完成了本案例,但是可以發現在做複雜一些的程式的話可能有很多類,若是都被放在一個檔案裡,簡直太長了,一般我們會将類放在其他的檔案下,讓項目結構更加清晰。
7.1.7.1 源檔案
#include<iostream>
#include<string>
#include "point.h"
#include "circle.h"
using namespace std;
//判斷點和圓關系
void isInCircle(Circle &c,Point &p)
{
//計算兩點之間距離的平方
int distance = (c.getCenter().getX() - p.getX()) * (c.getCenter().getX() - p.getX()) +
(c.getCenter().getY() - p.getY()) * (c.getCenter().getY() - p.getY());
//計算半徑的平方
int rDistance = c.getR() * c.getR();
//判斷關系
if (distance == rDistance)
{
cout << "點在圓上" << endl;
}
else if (distance > rDistance)
{
cout << "點在圓外" << endl;
}
else
{
cout << "點在圓内" << endl;
}
}
int main()
{
//建立圓
Circle c;
c.setR(10);
Point center;
center.setX(10);
center.setY(0);
c.setCenter(center);
//建立點
Point p;
p.setX(10);
p.setY(11);
//比較
isInCircle(c, p);
system("pause");
return 0;
}
4.1.7.2 point類
point.h
#pragma once
#include<iostream>
using namespace std;
class Point
{
public:
//設定x
void setX(int x);
//擷取x
int getX();
//設定y
void setY(int y);
//擷取y
int getY();
private:
int m_X;
int m_Y;
};
point.cpp
#include "point.h"
void Point::setX(int x)
{
m_X = x;
}
//擷取x
int Point::getX()
{
return m_X;
}
//設定y
void Point::setY(int y)
{
m_Y = y;
}
//擷取y
int Point::getY()
{
return m_Y;
}
4.1.7.3 circle類
circle.h
#pragma once
#include<iostream>
#include "point.h"
using namespace std;
class Circle
{
public:
//設定半徑
void setR(int r);
//擷取半徑
int getR();
//設定圓心
void setCenter(Point center);
//擷取圓心
Point getCenter();
private:
int m_R;
Point m_Center;//圓心
};
circle.cpp
#include "circle.h"
//設定半徑
void Circle::setR(int r)
{
m_R = r;
}
//擷取半徑
int Circle::getR()
{
return m_R;
}
//設定圓心
void Circle::setCenter(Point center)
{
m_Center = center;
}
//擷取圓心
Point Circle::getCenter()
{
return m_Center;
}
注意事項:
- .h檔案中隻寫成員函數聲明,具體函數實作寫在.cpp中
- .cpp寫函數時加上作用域并且包含對應的.h頭檔案