- c++ 的引用概念
int a = 100;
int &b = a; //在定义时使用 & 表示引用 , 给a 起一个别名, 也叫外号
printf(“a=%d\n”,a);
printf(“b=%d\n”,b);
printf("&b=%p\n",&b);
注意事项:1.引用必须在声明时立即初始化,不允许空引用
2.引用一旦初始化,就不能再引用其它数据
引用和被引用的变量实际上代表同一个内存的数据
变量存放到内存中会有个地址, 这个地址的别名就是引用 a和b共同表示同一块内存
- 传递函数的参数和返回值.C++中常用的方式有三种
值传递(赋值传参),指针传递(地址)和引用传递(等价于地址传递)
c++觉得c语言的指针不好理解, 弄出来引用来代替指针, 问题是没有代替成功,因此在c++中既可以用指针也可以用引用
int f1(int &x)
{
x ++;
return 0 ;
}
int f2(int *x)
{
(*x) ++;
return 0 ;
}
int main(int argc, char *argv[])
{
int a = 100;
f1(a);
printf(“a1=%d\n”,a);
f2(&a);
printf(“a2=%d\n”,a);
}
引用的主要目的是替换指针, 因此和指针的功能一样
-
引用和指针的混合使用
double a = 100; double& b = a; double *p = &b;
考察:(1)&a, p和&b的关系 -
因为标准库非常的庞大,所以程序员在选择的类的名称或函数名时就很有可能和标准库中的某个名字相同。
为了避免名字冲突,98年以后的c++语言提供一个全局的命名空间namespace就把标准库中的一切都被放在名字空间std中,
因此在程序中要对命名空间std作声明。
在程序中需要使用标准库时, 需要些下面一句话:
using namespace std;
也可以使用 std::strcpy();
-
c++ 中 :: 双冒号表示限定作用,
os.open() // python
std::strcpy() // c++ -
类的实现:
封装实例:
class Clock
{
public:
void SetTime(int NewH,int NewM,int NewS);
void ShowTime();
private:
int Hour,Minute,Second;
}; -
类的声明 也叫类的定义
类的声明形式
类是一种用户自定义类型,声明形式:
class 类名称
{
public:
公有成员(外部接口)
private:
私有成员
protected:
保护型成员
};
公有类型成员
在关键字public后面声明,它们是类与外部的接口,任何外部函数都可以访问公有类型数据和函数。
私有类型成员
在关键字private后面声明,只允许本类中的函数访问,而类外部的任何函数都不能访问。
保护类型
与private类似,其差别表现在继承与派生时对派生类的影响不同,在讲继承时再说明。
-
类的对象是该类的某一特定实体,即类类型的变量。
声明形式: 类名 对象名;
例: Clock myClock; -
类中成员的访问方式
类中成员互访
直接使用成员名
类外访问
使用“对象名.成员名”方式访问 public 属性的成员 -
成员数据与成员函数
成员数据
与一般的变量声明相同,但需要将它放在类的声明体中。
成员函数
在类中说明原型,可以在类外给出函数体实现,并在函数名前使用类名加以限定。
也可以直接在类中给出函数体,形成内联成员函数(inline)。
允许声明重载函数和带默认形参值的函数
11。 构造函数
-
构造函数的作用是在对象被创建时使用特定的值构造对象,或者说将对象初始化为一个特定的状态。
-
在对象创建时由系统自动调用。
-
如果程序中未声明,则系统自动产生出一个默认形式的构造函数
-
允许为内联函数、重载函数、带默认形参值的函数
-
构造函数名和类名同名 ,这个函数就是构造函数 , 可以有参数, 但不能有返回值
-
析构函数
-
和类的名字一样, 在类名前一个 ~ 做为析构函数
-
如果程序中未声明析构函数,编译器将自动产生一个默认的析构函数。
练习1:
封装一个圆,
私有成员: r(半径)
共有成员:
calc_girth()
calc_area()
用构造函数给定半径
- 拷贝构造函数
拷贝构造函数是一种特殊的构造函数,其形参为本类的对象引用
第一次:
i = 1,
a = 0;
b= -10;
c = 0
第二次:
i = 1, -> 33
a = 0; other.a= 2 -> 4
b= -10;other.b= 0 ->4
c = 8 other.c =10 ->15
i = 33, a=4,b = 0 , c 15
第三次输出:
i = 33
a = 0
b = -10
c = 8
第四次:
i = 43 +32 = 75
a = 0 other.a= 4 -> 6
b = -10 other.b =4
c = 8 other.c = 10 ->15
i = 75 a = 6 b=4,c=15
-
静态成员数据
在类的成员数据前加上一个static , 这个成员数据就是静态成员数据
该类的所有对象维护该成员的同一个拷贝
必须在类外定义和初始化,用(::)来指明所属的类 -
静态成员函数
类外代码可以使用类名和作用域(::)操作符来调用静态成员函数。
静态成员函数只能直接引用属于该类的静态数据成员或静态成员函数。 -
友元函数
友元函数是在类声明中由关键字friend修饰说明的非成员函数,在它的函数体中能够通过对象名访问 private 和 protected成员
访问对象中的成员必须通过对象名。
17.友元类
若一个类为另一个类的友元,则此类的所有成员都能访问对方类的私有成员。
声明语法:将友元类名在另一个类中使用friend修饰说明。
18.常类型
常类型的对象必须进行初始化,而且不能被更新。
常引用:被引用的对象不能被更新。
const 类型说明符 &引用名
常对象:必须进行初始化,不能被更新。
类名 const 对象名
常数组:数组元素不能被更新。
类型说明符 const 数组名[大小]…
常指针:指向常量的指针。
19.预处理命令:
#ifndef STUDENT_H // 如果没有定义这个宏
#define STUDENT_H // 定义这个宏
int a = 100;
#endif
20.类组合的构造函数设计
原则:不仅要负责对本类中的基本类型成员数据赋初值,也要对对象成员初始化。
声明形式:
类名::类名(对象成员所需的形参,本类成员形参)
:对象1(参数),对象2(参数),…
{ 本类初始化 }
练习1:
创建一个student 类 ,包含(id name , score)
再创建一个team 类 , 这个team中有4 学生组成
team中有一个方法, 计算一组学生成绩的平均分
21.派生类的声明
class 派生类名:继承方式 基类名
{
成员声明;
}
- 继承方式
公有继承 public
私有继承 private
保护继承 protected
23.不同继承方式的影响主要体现在:
派生类成员对基类成员的访问权限
通过派生类对象对基类成员的访问权限
24.公有继承(public)
基类的public和protected成员的访问属性在派生类中保持不变,但基类的private成员不可直接访问。
派生类中的成员函数可以直接访问基类中的public和protected成员,但不能直接访问基类的private成员。
通过派生类的对象只能访问基类的public成员。
25.私有继承(private)
基类的public和protected成员都以private身份出现在派生类中,但基类的private成员不可直接访问。
派生类中的成员函数可以直接访问基类中的public和protected成员,但不能直接访问基类的private成员。
通过派生类的对象不能直接访问基类中的任何成员。
26.保护继承(protected)
基类的public和protected成员都以protected身份出现在派生类中,但基类的private成员不可直接访问。
派生类中的成员函数可以直接访问基类中的public和protected成员,但不能直接访问基类的private成员。
通过派生类的对象不能直接访问基类中的任何成员
总结:
- 三种继承方式都不能访问父类中的private 成员函数
- 通过对象只有public继承方式,可以访问public成员,其余两种都不允许访问父类的任何成员
27.protected 成员的特点与作用
对建立其所在类对象的模块来说,它与 private 成员的性质相同。
对于其派生类来说,它与 public 成员的性质相同。
既实现了数据隐藏,又方便继承,实现代码重用
总结: protected : 在继承中,派生类的成员可以直接访问protected 和public成员,
由这个类创建的对象, 只能访问public成员
28.类型兼容规则
一个公有派生类的对象在使用上可以被当作基类的对象,反之则禁止。
具体表现在:
派生类的对象可以被赋值给基类对象。
派生类的对象可以初始化基类的引用。
指向基类的指针也可以指向派生类。
通过基类对象名、指针只能使用从基类继承的成员
练习1 :
设计一个基于对象的程序来求1个长方体的体积。
提示:数据成员包括length,width,height。
要求用成员函数实现一下功能:
1)由键盘分别输入1个长方体的长宽高
2)计算长方体的体积
3)输出1个长方体的体积
练习2:
设计一个程序实现以下功能。
商店销售某一商品,商店每天公布统一的折扣(discount)。同时允许销售人员在销售时灵活掌握售价(price),
在此基础上,对一次购10件以上者,还可以享受9.8折优惠。现已知当天3名销售员的销售情况为:
销售员号(num) 销售件数(quantity) 销售单价(price)
101 5 23.5
102 12 24.56
103 100 21.5
请编写程序,计算出当日此商品的总销售款sum以及每件商品的平均售价。(要求用静态数据成员和静态成员函数)
练习3:
以已有的学生类为基类,创建一个graduate类。编写一个程序实现以下功能:
1)graduate类增加了新的变量:tutor(家教),wage(工资)
2) graduate类也提供一个display函数,用来打印研究生类的信息
3)定义基类指针,去完成对display函数的调用。
练习4:
设计一个圆类circle和一个桌子类table,另设计一个圆桌类roundtable,它是从前两个类派生的,
要求输出一个圆桌的高度、面积和颜色等数据。
运算符重载(给这个符号另外一个含义)
1.可以重载C++中除下列运算符外的所有运算符:. .* :: ?: sizeof
哪一些运算符可以重载:
-
-
- / %
& , | , ~ ,^
&& || !
- / %
-
- , & , [] , - ++ – >> <<
= < < = == != ,
只能重载C++语言中已有的运算符,不可臆造新的。
不改变原运算符的优先级和结合性。
不能改变操作数个数。
经重载的运算符,其操作数中至少应该有一个是自定义类型。
重载为类成员函数。
重载为非成员函数(通常为友元函数)。
- 实现形式
函数类型 operator 运算符(形参)
{
…
}