C++ 支持面向对象程序设计。类是 C++ 的核心特性,通常被称为用户定义的类型。类用于指定对象的形式,类的成员包含数据表示法和用于处理数据的方法(函数)。
类和对象
类定义
类定义是以关键字 class 开头,后跟类的名称。类的主体是包含在一对花括号中。类定义后必须跟着一个分号或一个声明列表:
class ClassName
{
public:
memberType memberName1;
.
.
.
memberType memberNameN;
]
关键字 public 确定了类成员的访问属性。在类对象作用域内,公共成员在类的外部是可访问的。也可以指定类的成员为 private 或 protected
对象定义
类提供了对象的蓝图,对象是根据类来创建的。声明类的对象,就像声明基本类型的变量一样。对象定义的语法格式:
className objectName;
数据成员访问
类的对象的公共数据成员可以使用直接成员访问运算符 (.) 来访问。对于上面所述,举一个综合例子:
#include <iostream>
using namespace std;
class Box
{
public:
double length; // 长度
double breadth; // 宽度
double height; // 高度
};
int main( )
{
Box box; // 声明 box对象,类型为 Box
double volume = 0.0; // 用于存储体积
// box 详述
box.height = 5.0;
box.length = 6.0;
box.breadth = 7.0;
// box 的体积
volume = box.height * box.length * box.breadth;
cout << "box 的体积:" << volume <<endl;
return 0;
}
注意:私有的成员和受保护的成员不能使用直接成员访问运算符 (.)来直接访问。
类成员函数
类的成员函数是指那些把定义和原型写在类定义内部的函数,就像类定义中的其他变量一样。类成员函数是类的一个成员,它可以操作类的任意对象,可以访问对象中的所有成员。成员函数可以定义在类定义内部,或者单独使用范围解析运算符 :: 来定义。
1. 定义在类定义内部:
class Box
{
public:
double length; // 长度
double breadth; // 宽度
double height; // 高度
double getVolume(void)
{
return length * breadth * height;
}
};
2. 在类的外部使用范围解析运算符 :: 定义成员函数:
class Box
{
public:
double length; // 长度
double breadth; // 宽度
double height; // 高度
};
double Box::getVolume(void)
{
return length * breadth * height;
}
调用成员函数是在对象上使用点运算符(.)。
类访问修饰符
数据封装是面向对象编程的一个重要特点,它防止其他非本类函数直接访问类的内部成员。关键字 public、private、protected 称为访问修饰符,访问权限从大到小:public > protected > private。成员和类的默认访问修饰符是 private。
公有(public)成员
公有成员在程序中类的外部是可访问的。在类外部,可以不使用任何成员函数,直接通过成员运算符(.)访问公有成员。访问公有成员就存在来两种方式:
#include <iostream>
using namespace std;
class Line
{
public:
double length;
void setLength( double len );
};
void Line::setLength( double len )
{
length = len;
}
// 程序的主函数
int main( )
{
Line line;
// 设置长度
return 0;
}
通过成员函数:
line.setLength(6.0);
直接访问公有成员:
line.length = 10.0;
私有(private)成员
私有成员变量或函数在类的外部(类定义外)是不可访问的,甚至是不可查看的。只有类和友元函数可以访问私有成员。
默认情况下,类的所有成员都是私有的。实际操作中,我们一般会在私有区域定义数据,在公有区域定义相关的函数,在类的外部用成员函数来访问私有成员。
#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;
}
// 程序的主函数
int main( )
{
Box box;
// length 是公有的,可以不使用成员函数设置长度
box.length = 10.0;
//width 是私有的,使用成员函数才可以设置宽度
box.setWidth(10.0); //
return 0;
}
保护(protected)成员
保护成员变量或函数与私有成员十分相似,但有一点不同,保护成员在派生类(即子类)中是可访问的。
保护成员可被派生类的任何成员函数访问:
#include <iostream>
using namespace std;
class Box
{
protected:
double width;
};
class SmallBox:Box // SmallBox 是派生类
{
public:
void setSmallWidth( double wid );
};
// 子类的成员函数
void SmallBox::setSmallWidth( double wid ){
//width是保护成员,子类的成员函数可以访问
width = wid;
}
// 程序的主函数
int main( )
{
SmallBox box;
// 使用成员函数设置宽度
box.setSmallWidth(5.0);
return 0;
}
继承
创建类时,只需指定新建的类继承了一个已有的类的成员(数据成员和成员函数)即可。这个已有的类称为基类,新建的类称为派生类。继承代表了 is a 关系。例如,哺乳动物是动物,狗是哺乳动物,因此,狗是动物,等等。
基类 & 派生类
一个类可以派生自多个类,这意味着,它可以从多个基类继承数据和函数。定义一个派生类,我们使用一个类派生列表来指定基类。类派生列表以一个或多个基类命名,形式如下:
//类 派生类: 访问修饰符 基类
class derived-class: access-specifier base-class
派生类继承了所有的基类方法,但下列情况除外:
- 基类的构造函数、析构函数和拷贝构造函数。
- 基类的重载运算符。
- 基类的友元函数。
多继承
多继承即一个子类可以有多个父类,它继承了多个父类的特性。语法如下:
class <派生类名>:<继承方式1><基类名1>,<继承方式2><基类名2>,…
{
<派生类类体>
};
另外多继承(环状继承(继承链出现环)),A->D, B->D, C->(A,B)。
class D{......};
class B: public D{......};
class A: public D{......};
class C: public B, public A{.....};
这个继承当使用C创建对象的时候,会使D创建两个对象,要解决上面问题就要用虚拟继承(虚继承——在创建对象的时候会创建一个父类对象的虚表),语法为:
class D{......};
class B: virtual public D{......};
class A: virtual public D{......};
class C: public B, public A{.....};
继承方式
因此具有public, protected, private三种继承方式,不大于继承方式的基类(父类)成员的访问属性不变,大于继承方式的基类(父类)成员的访问属性变成继承方式 (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 成员可以被派生类访问。
如果继承时不显示声明是 private,protected,public 继承,则默认是 private 继承,而在 struct 中默认 public 继承
#include<iostream>
#include<assert.h>
using namespace std;
class A{
public:
int a;
A(){
a1 = 1;
a2 = 2;
a3 = 3;
a = 4;
}
void fun(){
cout << a << endl; //正确
cout << a1 << endl; //正确
cout << a2 << endl; //正确
cout << a3 << endl; //正确
}
public:
int a1;
protected:
int a2;
private:
int a3;
};
//public 继承
class B : public A{
public:
int a;
B(int i){
A();
a = i;
}
void fun(){
cout << a << endl; //正确,public成员
cout << a1 << endl; //正确,基类的public成员,在派生类中仍是public成员。
cout << a2 << endl; //正确,基类的protected成员,在派生类中仍是protected可以被派生类访问。
cout << a3 << endl; //错误,基类的private成员不能被派生类访问。
}
};
// protect继承
class B : protect A{
public:
int a;
B(int i){
A();
a = i;
}
void fun(){
cout << a << endl; //正确,public成员。
cout << a1 << endl; //正确,基类的public成员,在派生类中变成了protected,可以被派生类访问。
cout << a2 << endl; //正确,基类的protected成员,在派生类中还是protected,可以被派生类访问。
cout << a3 << endl; //错误,基类的private成员不能被派生类访问。
}
};
//private 继承
class B : private A{
public:
int a;
B(int i){
A();
a = i;
}
void fun(){
cout << a << endl; //正确,public成员。
cout << a1 << endl; //正确,基类public成员,在派生类中变成了private,可以被派生类访问。
cout << a2 << endl; //正确,基类的protected成员,在派生类中变成了private,可以被派生类访问。
cout << a3 << endl; //错误,基类的private成员不能被派生类访问。
}
};
int main(){
B b(10);
//类外可以访问public成员
//类外不能访问protected成员
//类外不能访问private成员
cout << b.a << endl;
cout << b.a1 << endl;
cout << b.a2 << endl;
cout << b.a3 << endl;
system("pause");
return 0;
}
本节内容较多,篇幅过长,影响心情,请继续:C++进阶学习一去不复返系列:类和对象(二) <= 传送门 。