C++基础学习第一天
类与对象
struct与class
聚合类
最初的C++称为“带类的C”,扩展了C语言的很多功能。在C++语言中,仍然可以使用C语言中的struct
定义结构。
struct 结构名{
类型 变量名;
类型 变量名;
...
}
在C++中,聚合类是一种特殊类型的类,用户可以直接访问其成员,并且具有特殊的初始化语法形式(可以提供一对花括号括起来的成员初始值列表初始化聚合类的数据成员)。
聚合类应当满足的条件:
- 所有的成员都是
public
类型的(任何情况下,对象都可以通过成员运算符访问成员); - 没有定义任何构造函数;
- 没有类内初始值;
- 没有基类,也没有虚函数。
举个例子,定义一个聚合类Data
:
struct Data{
int ival;
string str;
};
初始化可以这样:
Data dval = {8,"Smith"};
注意:初始值的顺序必须与成员声明的顺序一致。初始值列表中元素的个数如果少于类的成员数量,则靠后的成员被值初始化。初始值列表中元素的个数绝对不能少于类的成员数量。
C++对struct的扩展
C++中的struct
不仅可以包含数据,还可以包含函数。
举个例子:
#include<iostream>
using namespace std;
struct Complex{
double real;
double imag;
void init(double r,double i){
real = r;
imag = i;
}
double getReal(){return real;}
double getImag(){return imag;}
};
int main(){
Complex c;
c.init(2,3);
cout <<c.getReal() <<"+" <<c.getImag() <<"i" <<endl;
return 0;
}
小提示:在结构中数据成员后面带分号,函数成员后面是不带分号的,但是函数成员内需要带分号,结构反括号后面也是要加分号的,main
结束是不加分号的。
说明:结构中的数据和函数称为成员,real
、imag
是数据成员。定义Complex
结构后,就可以用它来定义变量,并能通过成员运算符访问它的成员函数。
访问权限
为了实现信息隐藏,限制对结构中某些成员的非法访问,C++增高了3个访问权限限定符,用于设置结构中数据成员和函数成员的访问权限。
-
public
被设置为
public
权限的成员(包括数据成员和函数成员)称为类的公有成员,可被任何函数访问(包括结构内和结构外的函数)。 -
private
被设置为
private
权限的成员(包括数据成员和函数成员)称为类的私有成员,仅供结构(类)的内部(自身成员函数)访问。 -
protected
protected
与继承有关。供结构(类)的内部及后代(派生类)访问。
在C和C++中,如果没有声明访问权限,默认的访问权限是public
。如果不想让外部直接访问需要加个private
声明为私有类型。C++结构的定义形式:
struct 类名{
[public:]
成员;
private:
成员;
protected:
成员;
};
类
类(class)具有信息隐藏的能力,能够完成接口与实现的分离,用于把数据抽象的结果封装成可以用于程序设计的抽象数据类型。是面向对象程序设计中通用的数据封装工具。在C++中,class
具有与struct
完全相同的功能,用法一致。类是默认private
。
类也是一种自定义数据类型,用关键字class
表示,用法与struct
相同,形式如下:
class 类名{
[private:]
成员;
public:
成员;
protected:
成员;
};
类名通常首字符大写的标识符表示 ;一对花括号界定了类的范围;最后的分号必不可少,表示类声明结束。
举个例子:
class Complex
{
private:
double real,imag;
public:
void init(double r,double i){
real = r;
imag = i;
}
double getReal(){return real;}
double getImag(){return imag;}
void print(){
cout <<c.getReal() <<"+" <<c.getImag() <<"i" <<endl;
}
};
对于类定义需要注意的问题:
-
访问说明符
对于类声明中的访问说明符
private
、public
和protected
没有先后主次之分,也没有使用次数的限制。只是出于信息隐藏的目的,将数据成员设置为private
权限,将需要让外部函数访问的成员设置为public
权限。 -
类作用域
class
或struct
后面的一对花括号包围的区域是一种独立的作用域,称为类域。类域内的数据和函数都称为成员(数据称为数据成员,函数常被称为成员函数)。同一类域内的成员是不爱访问权限和先后次序的限制,相互间可以直接访问。 -
关键字struct和class
C++的
struct
也是一种类,它与class
具有相同的功能,用法也是完全相同。唯一区别是在没有指定成员的访问权限时,默认的权限是不一样的。
抽象与封装
类是对客观世界中同类事物的抽象,它给出了属于该类事物共有的属性(数据成员)和操作(成员函数)。
类具有封装特性。
- 能够把数据和算法组合在一起,构成一个不可分割的整体;
- 能够有效地把类的内部数据隐藏起来,外部函数只能通过类的公有成员才能访问类的内部数据。
抽象是对具体对象(问题)进行概括,抓住问题的本质,抽出这一类对象共有的性质,并加以描述的过程,抽象主要包括数据抽象和过程抽象。
抽象与封装的区别:抽象是一种思维方式,而封装是一种基于抽象性的操作方法。一般通过抽象,把所得到的数据信息以封装的技术将其重新整合,形成一个新的有机体,这就是类。
类的成员
数据成员
类的数据成员可以是任何数据类型,如整型、浮点型、字符型、数组、指针和引用等,也可以是另外一个类的对象或指向对象的指针,还可以是自身类的指针或引用,但不能是自身类的对象;可以是const
常量,但不能是constexpr
常量;可以用decltype
推断类型,但不能使用auto
推断类型;数据成员不能指定为extern
的存储类别。
C++支持在定义类的同时为类的数据成员赋初始值,举个例子:
class X{
private:
int a = 2;
int y = {3};
int b[3] = {1,2,3};
const int ci = a;
public:
...
}
注意:类的定义或声明只是在程序中增加的自定义数据类型,是没有分配相应的内存空间。只有在实例化时,才会分配相应的空间,也才会在这时初始化数据成员。
成员函数
类的成员函数也称为方法或服务。它可以在类内定义,也可以在类外定义;可以重载,也可以使用默认实参。
-
成员函数的定义
类的成员函数有两种定义方式:
-
声明类时就给出成员函数的定义。
class Complex { private: double real,imag; public: void init(double r,double i){ real = r; imag = i; } double getReal(){return real;} double getImag(){return imag;} };
-
在声明类时,只声明成员函数的原型,然后在外部定义成员函数。类外定义函数格式
返回类型 类名::成员函数名(参数列表);
其中,
::
是作用域运算符,用于说明这里定义的函数是指定类中的一个成员函数。class Complex { private: double real,imag; public: void init(double r,double i); double getReal(); double getImag(); }; void Complex::init(double r,double i){ real = r; imag = i; } void Complex::getReal(){ return real; } void Complex::getImag(){ return imag; }
-
-
const(常量)成员函数
为了禁止成员函数修改数据成员的值,可以将它设置为
const
(常量)成员函数。设置的方法是在成员函数形参列表的后面加上关键字const
,格式如下:class X{ T f(T1,T2,...) const; };
说明:
T
是函数返回类型,f
是函数名,T1
,T2
是各参加的类型。将成员函数设置为const
类型后,表明该成员函数不会修改任何成员的值。注意:只有类的成员函数才能指定为常量,一般的函数是一能的。
const
成员函数与const
参数是不同的。 -
成员函数的重载与默认实参
类的函数是可以重载,也可以指定默认实参。
在外定义的函数,只能在声明时或类外定义成员函数时才能指定默认实参,但不能在声明和定义中同时指定。
嵌套类型
嵌套类型是在类中定义的类、枚举、使用typedef
声明为成员的任意类型以及使用using声明的类型别名。
-
嵌套类
- 定义在另一个类的内部的类称作嵌套类,嵌套类也是一个独立的类,与外层类基本没有关系;
- 外层类的对象和嵌套类的对象是相互独立的,嵌套类对象中不包含任何外层类定义的成员,外层类也不包含嵌套类定义的成员;
- 嵌套类的访问权限由外层类决定;
- 外层类对嵌套类的成员没有特殊的访问权限,嵌套类对外层类的成员也没有访问权限;
class X{ ... class Y{ //Y是在X类定义的嵌套类 ... } };
- 嵌套类也可以在类内声明,类外定义(需要外层类类型来限定)。
class X{ ... public: class Y; //Y是X的嵌套类,定义在外层类之外 }; class X::Y{ //Y是在X类外定义的嵌套类 ... }
-
类型别名
在类内部可以使用
typedef
和using
声明类型别名。typedef T alias; using alias = T;
类类型与对象
通过class定义的类型称为类类型,由类类型定义的变量称为对象。
类类型
不同类类型的对象不能进行自动相互转换,即使两个类具有完全相同的成员列表,它们也是不同类型,是不能进行自动类型转换。
可以直接把类名作为类型的名字来用,从而直接指向类类型。也可以把类名跟关键字后面来使用。
Complex c; //默认初始化Complex类型的对象
class Complex c; //等价声明
类的声明和定义是可以分开的,可以先声明类,而暂时不定义它。
class C; //C类的声明
对象
类是对同类事物的一种抽象,这类事物中具体的一个实例就把它看作一个对象。类和对象的关系就是数据类型和变量的关系。
-
对象的定义
用类定义对象的形式如下:
类类型名 对象名;
类类型是一种自定义类类型,可以定义类型的变量,也可以定义类类型的指针和引用。
Clock* p = &cl1; //定义Clock类的指针p指向对象cl1 Clock& r = cl2; //定义Clock类的引用r指向对象cl2
-
对象对成员的访问
类中成员之间可以相互访问,不受访问说明符的限制,可以直接使用成员名。类外使用只能使用“对象名.成员名”访问具有public访问说明符的成员。对象引用方法与结构相似,必须用成员运算符“.”作为对象名和对象成员之间的间隔符,格式如下:
对象名.数据成员名 对象名.成员函数名(实参列表) clk1.setHour(12); clk1.print();
说明:类外只能访问对象的公有成员,不能访问对象的私有和受保护成员;如果定义的对象指针,在通过指针访问对象成员时,要用成员运算符“->”作为指针对象和对象成员之间的间隔符。
-
对象间的赋值
不同类类型的对象之间不能互相赋值。同类的不同对象之间,以及同类的指针之间可以相互赋值。
对象名1 = 对象名2;
说明:进行赋值两个对象类型必须相同;进行数据成员的值复制,赋值之后,两不相干。