C++ | C++ 类 & 对象
C++ 在 C 语言的基础上增加了面向对象编程,C++ 支持面向对象程序设计。类是 C++ 的核心特性,通常被称为用户定义的类型。
类用于指定对象的形式,它包含了数据表示法和用于处理数据的方法。类中的数据和方法称为类的成员。函数在一个类中被称为类的成员。
C++ 类定义
定义一个类,本质上是定义一个数据类型的蓝图。这实际上并没有定义任何数据,但它定义了类的名称意味着什么,也就是说,它定义了类的对象包括了什么,以及可以在这个对象上执行哪些操作。
class BOX
{
public:
double length; // 长度
double width; // 宽度
double height; // 高度
};
定义 C++ 对象
类提供了对象的蓝图,所以基本上,对象是根据类来创建的。声明类的对象,就像声明基本类型的变量一样。声明了类 Box 的两个对象:
BOX box1; /* 声明一个对象box1,类型BOX */
BOX box2; /* 声明一个对象box2,类型BOX */
对象 box1 和 box2 都有它们各自的数据成员。
访问数据成员
类的对象的公共数据成员可以使用直接成员访问运算符 . 来访问。
实例1:
/*******************************************************************
* > File Name: class1.cpp
* > Create Time: 2021年09月 2日 14:02:41
******************************************************************/
#include <iostream>
using namespace std;
class Box{
public:
double length; /* 长度 */
double width; /* 高度 */
double height; /* 宽度 */
double get(void); /* 成员函数声明 */
void set(double len, double wid, double hei); /* 成员函数声明 */
};
/* 成员函数定义 */
double Box::get(void)
{
return length*width*height;
}
void Box::set(double len, double wid, double hei)
{
length = len;
width = wid;
height = hei;
}
int main(void)
{
Box box1;
Box box2;
Box box3;
double volume = 0.0;
box1.height = 10.0;
box1.width = 10.0;
box1.height = 10.0;
box2.height = 5.0;
box2.width = 5.0;
box2.height = 5.0;
volume = box1.height*box1.width*box1.height;
cout << "The volume of box1: " << volume << endl;
volume = box2.height*box2.width*box2.height;
cout << "The volume of box2: " << volume << endl;
box3.set(6.0, 6.0, 6.0);
cout << "The volume of box3: " << box3.get() << endl;
return 0;
}
编译、运行:
PS E:\fly-prj\cplusplus\day4> make
g++ -o class1 class1.cpp -g -Wall
PS E:\fly-prj\cplusplus\day4> .\class1.exe
The volume of box1: 1000
The volume of box2: 125
The volume of box3: 216
私有的成员和受保护的成员不能使用直接成员访问运算符 (.) 来直接访问。
类 & 对象详解
C++ 类成员函数
类的成员函数是指那些把定义和原型写在类定义内部的函数,就像类定义中的其他变量一样。类成员函数是类的一个成员,它可以操作类的任意对象,可以访问对象中的所有成员。
成员函数可以定义在类定义内部,或者单独使用范围解析运算符 :: 来定义。在类定义中定义的成员函数把函数声明为内联的,即便没有使用 inline 标识符。
在这里,需要强调一点,在 :: 运算符之前必须使用类名。调用成员函数是在对象上使用点运算符(.),这样它就能操作与该对象相关的数据。
实例2:
/*******************************************************************
* > File Name: class2.cpp
* > Create Time: 2021年09月 2日 14:41:22
******************************************************************/
#include <iostream>
using namespace std;
class BOX{
public:
int length;
int width;
int height;
double getVolume(void);
void setLength(double len);
void setWidth(double wid);
void setHeight(double hei);
};
double BOX::getVolume(void)
{
return length*width*height;
}
void BOX::setLength(double len)
{
length = len;
}
void BOX::setWidth(double wid)
{
width = wid;
}
void BOX::setHeight(double hei)
{
height = hei;
}
int main(void)
{
BOX box1;
double volume = 0.0;
box1.setLength(5.0);
box1.setWidth(5.0);
box1.setHeight(5.0);
volume = box1.getVolume();
cout << "The volume of box1: " << volume << endl;
return 0;
}
编译、运行:
PS E:\fly-prj\cplusplus\day4> make
g++ -o class2 class2.cpp -g -Wall
PS E:\fly-prj\cplusplus\day4> .\class2.exe
The volume of box1: 125
C++ 类访问修饰符
数据封装是面向对象编程的一个重要特点,它防止函数直接访问类类型的内部成员。类成员的访问限制是通过在类主体内部对各个区域标记 public、private、protected 来指定的。关键字 public、private、protected 称为访问修饰符。
一个类可以有多个 public、protected 或 private 标记区域。每个标记区域在下一个标记区域开始之前或者在遇到类主体结束右括号之前都是有效的。成员和类的默认访问修饰符是 private。
公有(public)成员
公有成员在程序中类的外部是可访问的。您可以不使用任何成员函数来设置和获取公有变量的值。
私有(private)成员
私有成员变量或函数在类的外部是不可访问的,甚至是不可查看的。只有类和友元函数可以访问私有成员。
默认情况下,类的所有成员都是私有的。
实际操作中,我们一般会在私有区域定义数据,在公有区域定义相关的函数,以便在类的外部也可以调用这些函数。
实例3:
/*******************************************************************
* > File Name: class3.cpp
* > Create Time: 2021年09月 2日 15:10:21
******************************************************************/
#include <iostream>
using namespace std;
class BOX{
public:
double length;
void setWidth(double wid);
double getWidth(void);
private:
double width;
};
void BOX::setWidth(double wid)
{
width = wid;
}
double BOX::getWidth(void)
{
return width;
}
int main(void)
{
BOX box1;
box1.length = 1.0; // OK:length变量是公开的
cout << "the length of box1: " << box1.length << endl;
box1.setWidth(2.0); // OK:使用成员函数设置宽度
//box1.width = 2.0; // error:‘double BOX::width’ is private within this context
cout << "the width of box1: " << box1.getWidth() << endl;
return 0;
}
编译、运行:
PS E:\fly-prj\cplusplus\day4> make
g++ -o class3 class3.cpp -g -Wall
PS E:\fly-prj\cplusplus\day4> .\class3.exe
the length of box1: 1
the width of box1: 2
protected(受保护)成员
**protected(受保护)**成员变量或函数与私有成员十分相似,但有一点不同,protected(受保护)成员在派生类(即子类)中是可访问的。
实例4:
/*******************************************************************
* > File Name: class4.cpp
* > Create Time: 2021年09月 2日 15:42:53
******************************************************************/
#include <iostream>
using namespace std;
class BOX{
protected:
double width;
};
class smallBox:BOX{ // 派生类smallBox
public:
void setSmallBoxWidth(double wid);
double getSmallBoxWidth(void);
};
/* 子类的成员函数 */
void smallBox::setSmallBoxWidth(double wid)
{
width = wid;
}
double smallBox::getSmallBoxWidth(void)
{
return width;
}
int main(void)
{
smallBox box1;
box1.setSmallBoxWidth(1.0); /* 使用成员函数设置宽度 */
cout << "The width of box1: " << box1.getSmallBoxWidth() << endl;
return 0;
}
编译、运行:
PS E:\fly-prj\cplusplus\day4> make
g++ -o class4 class4.cpp -g -Wall
PS E:\fly-prj\cplusplus\day4> .\class4.exe
The width of box1: 1
继承中的特点
有public, protected, private三种继承方式,它们相应地改变了基类成员的访问属性。
- 1.**public 继承:**基类 public 成员,protected 成员,private 成员的访问属性在派生类中分别变成:public, protected, private
- 2.**protected 继承:**基类 public 成员,protected 成员,private 成员的访问属性在派生类中分别变成:protected, protected, private
- 3.**private 继承:**基类 public 成员,protected 成员,private 成员的访问属性在派生类中分别变成:private, private, private
但无论哪种继承方式,上面两点都没有改变:
- 1.private 成员只能被本类成员(类内)和友元访问,不能被派生类访问;
- 2.protected 成员可以被派生类访问。
public 继承
构造函数 ,是一种特殊的方法。主要用来在创建对象时初始化对象, 即为对象成员变量赋初始值,总与new运算符一起使用在创建对象的语句中。特别的一个类可以有多个构造函数 ,可根据其参数个数的不同或参数类型的不同来区分它们 即构造函数的重载。
实例5:
/*******************************************************************
* > File Name: classPublic.cpp
* > Create Time: 2021年09月 2日 16:15:49
******************************************************************/
#include <iostream>
using namespace std;
class A{
public:
int a;
A(){ /* 构造函数 */
a1 = 1;
a2 = 2;
a3 = 3;
a = 4;
}
void func(){
cout << a << endl; // OK
cout << a1 << endl; // OK
cout << a2 << endl; // OK
cout << a3 << endl; // OK
}
public:
int a1;
protected:
int a2;
private:
int a3;
};
class B:public A{ /* 派生类 */
public:
int a;
B(int i){
A();
a = i;
}
void func(){
cout << a << endl; // OK
cout << a1 << endl; // OK,在派生类中仍然是public
cout << a2 << endl; // OK,在派生类中仍然是protected
/* 基类的private不能被派生类访问 */
//cout << a3 << endl; // Err:‘int A::a3’ is private within this context
}
};
int main(void)
{
B b(10);
cout << b.a << endl; // OK
cout << b.a1 << endl; // OK
//cout << b.a2 << endl; // Err:‘int A::a2’ is protected within this context
//cout << b.a3 << endl; // Err:‘int A::a3’ is private within this context
return 0;
}
编译、运行:
PS E:\fly-prj\cplusplus\day4> make
g++ -o classPublic classPublic.cpp -g -Wall
PS E:\fly-prj\cplusplus\day4> .\classPublic.exe
10
1
protected 继承
实例5:
/*******************************************************************
* > File Name: classProtected.cpp
* > Create Time: 2021年09月 2日 16:50:31
******************************************************************/
#include <iostream>
using namespace std;
class A{
public:
int a;
A(){
a1 = 1;
a2 = 2;
a3 = 3;
a = 4;
}
void func(void){
cout << a << endl; // OK
cout << a1 << endl; // OK
cout << a2 << endl; // OK
cout << a3 << endl; // OK
}
public:
int a1;
protected:
int a2;
private:
int a3;
};
class B:protected A{
public:
int a;
B(int i){
A();
a = i;
}
void func(void){
cout << a << endl; // OK,public
cout << a1 << endl; // OK,在派生类中变成protected
cout << a2 << endl; // OK,在派生类中变成protected
//cout << a3 << endl; // ERR:‘int A::a3’ is private within this context
}
public:
protected:
private:
};
int main(void)
{
B b(10);
cout << b.a << endl; // OK,public
//cout << b.a1 << endl; // ERR:‘int A::a1’ is inaccessible within this context
//cout << b.a2 << endl; // ERR:‘int A::a2’ is protected within this context
//cout << b.a3 << endl; // ERR:‘int A::a3’ is private within this context
return 0;
}
编译、运行:
PS E:\fly-prj\cplusplus\day4> make
g++ -o classProtected classProtected.cpp -g -Wall
PS E:\fly-prj\cplusplus\day4> .\classProtected.exe
10
private 继承
实例6:
/*******************************************************************
* > File Name: classPrivate.cpp
* > Create Time: 2021年09月 2日 17:22:09
******************************************************************/
#include <iostream>
using namespace std;
class A{
public:
int a;
A(){
a1 = 1;
a2 = 2;
a3 = 3;
a = 4;
}
void func(){
cout << a << endl; // OK
cout << a1 << endl; // OK
cout << a2 << endl; // OK
cout << a3 << endl; // OK
}
public:
int a1;
protected:
int a2;
private:
int a3;
};
class B:private A{
public:
int a;
B(int i){
A();
a = i;
}
void func(void){
cout << a << endl; // OK,public成员
cout << a1 << endl; // OK,派生类中变成private,可以被派生类访问
cout << a2 << endl; // OK,派生类中变成private,可以被派生类访问
//cout << a3 << endl; // ERR:‘int A::a3’ is private within this context
}
};
int main(void)
{
B b(10);
cout << b.a << endl; // OK,public成员
/* private成员在类外不可被访问 */
//cout << b.a1 << endl; // ERR:‘int A::a1’ is inaccessible within this context
//cout << b.a2 << endl; // ERR:‘int A::a2’ is protected within this context
//cout << b.a3 << endl; // ERR:‘int A::a3’ is private within this context
return 0;
}
编译、运行:
PS E:\fly-prj\cplusplus\day4> make
g++ -o classPrivate classPrivate.cpp -g -Wall
PS E:\fly-prj\cplusplus\day4> .\classPrivate.exe
10
总结一下三种继承方式:
继承方式
| 基类的public成员
| 基类的protected成员
| 基类的private成员
| 继承引起的访问控制关系变化概括
|
public继承
| 仍为public成员
| 仍为protected成员
| 不可见
| 基类的非私有成员在子类的访问属性不变
|
protected继承
| 变为protected成员
| 变为protected成员
| 不可见
| 基类的非私有成员都为子类的保护成员
|
private继承
| 变为private成员
| 变为private成员
| 不可见
| 基类中的非私有成员都称为子类的私有成员
|