类与对象:
{
类的构成:{
把具有共同属性和行为的事物所构成的集合称为类
类声明中包含数据和函数 即 数据成员和成员函数
访问权限分为 public公有、private私有、protected保护 三种
格式:{
class 类名{
public:
公有数据成员;
公有成员函数;
protected:
保护数据成员;
保护成员函数;
private:
私有数据成员;
私有成员函数;
};
}
class Score{
public:
void setScore(int s);
void showScore();
private:
int mid_exam;
int fin_exam;
};
注释:一般的 一个类的数据成员声明为私有成员 成员函数声明为公有成员
私有部分处于类的第一部分时 关键字private可以省略
一个类中没有访问权限关键字 默认为私有
不能在类声明中给数据成员赋初值
}
成员函数定义:{
普通成员函数的定义 其形式如下:
返回值类型 类名::成员函数名(参数表) { 函数体 }
在类的声明中 只给出成员函数的原型 定义在类的外部
eg: {
class Score{
public:
void setScore(int mid, int fin);
void showScore();
private:
int mid_exam;
int fin_exam;
};void Score::setScore(int mid, int fin)
{
mid_exam = mid;
fin_exam = fin;
}
void Score::showScore(void)
{
cout << "mid_exam = " << mid_exam << endl;
cout << "fin_exam = " << fin_exam << endl;
}
int main()
{
Score s1;
s1.setScore(80, 90);
s1.showScore();
return 0;
}
}
内联成员函数定义:{
隐式声明 将成员函数直接定义在类内部
显示声明 在类声明中只给函数原型 定义在类外部
}
eg:{
// 隐式内联成员函数
class Score{
public:
int add(int a, int b)
{
.....
}
private:
....
};
// 显示内联成员函数
class Student{
public:
inline int add(int a, int b);
private:
...
};
inline int Student::add(int a, int b)
{
...
}
注释 :用inline定义的内联函数 声明和定义须在同一文件中 否则编译器无法区分
}
}
对象的定义及使用:{
声明类的同时 直接定义对象
eg:{
class Score{
public:
void setScore(int mid, int fin);
void showScore();
private:
int mid_exam;
int fin_exam;
}op1, op2; // 定义两个对象op1和op2
}
声明类后 定义对象
eg:{
Score s1, s2; // 定义两个对象s1和s2
}
对象中成员的访问 形式如下
对象名.数据成员名 或 对象名.成员函数名(参数列表)
eg:{
op1.setScore(80, 90);
op1.showScore();
}
注释:
类的内部所有成员之间都可通过成员函数直接访问 类的外部 不能访问对象的私有成员
定义对象时 若是指向此对象的指针变量 则用'->'操作符访问成员对象
eg:{
Score *p ;
p->setScore(80, 90);
}
类的作用域及类成员的访问属性:{
私有成员只能被类中成员函数访问 不能在类外部通过类的对象进行访问
一般来说 公有成员是类的对外接口 私有成员是类的内部数据和内部实现
类的访问级别优点 信息隐藏 数据保护
}
}
构造函数与析构函数:{
构造函数:{
构造函数是一种特殊的成员函数 主要用于为对象分配空间 进行初始化
构造函数的名称与类名相同 无返回值 参数类型任意(可不带参数)
构造函数的调用方式 无需显示调用 系统在创建对象时自动调用 且只执行一次
eg:{
class Score{
public:
Score(int mid, int fin); // 构造函数
void setScore(int mid, int fin);
void showScore();
private:
int mid_exam;
int fin_exam;
};
Score::Score(int mid, int fin)
{
mid_exam = mid;
fin_exam = fin;
}
}
建立对象时 采用构造函数给数据成员赋值 形式如下
类名 对象名(参数表)
Score s1(80, 90);
s1.showScore();
类名 *指针变量名 = new 类名(参数表)
Score *p = new Score(80, 90); // 同Score *p; p = new Score(80, 90);
p->showScore();
}
成员初始化列表:{
数据成员的初始化一般在构造函数中进行 也可使用成员初始化列表实现数据成员初始化
格式:
类名::构造函数名(参数表): 数据成员名1(初值1), 数据成员名2(初值2), ...
{
// 构造函数体
}
eg:{
class Animal{
private:
int age;
int& a_age;
const double pi;
public:
Animal(int v):age(v), a_age(age), pi(3.14)
{
}
void show()
{
cout << "age = " << age << "a_age =" << a_age << "pi = " << pi << endl;
}
};
}
类成员初始化顺序按照声明顺序进行
}
带默认参数的构造函数:{
eg:{
class Score{
public:
Score(int mid = 0, int fin = 0);
...
private:
int mid_exam;
int fin_exam;
};
Score::Score(int mid, int fin):mid_exam(mid), fin_exam(fin)
{
cout << "构造函数使用中...." << endl;
}
}
}
析构函数:{
析构函数也是一种特殊的成员函数 执行与构造函数相反的操作
通常用于撤销对象时一些清理任务 如释放分配给对象的内存空间
析构函数特点
析构函数与构造函数名相同 前面一个'~'
析构函数无参数 无返回值 不能重载
撤销对象时 系统自动调用析构函数
eg:{
class Score{
public:
Score(int mid, int fin); // 构造函数
~Score(); // 析构函数
private:
int mid_exam;
int fin_exam;
};
Score::Score(int mid, int fin) : mid_exam(mid), fin_exam(fin)
{
cout << "构造函数使用中...." << endl;
}
Score::~Score()
{
cout << "析构函数使用中...." << endl;
}
}
}
默认的构造函数和析构函数:{
若未定义构造函数 则系统自动生成一个默认的构造函数
对未定义构造函数的类 其公有数据成员可用初始值列表进行初始化
eg:{
class Stu{
public:
char name[10];
int no;
};
Stu s1 = {"张三", 1001};
cout << s1.name << " " << s1.no << endl;
}
若未定义析构函数 则系统自动生成默认析构函数
}
构造函数的重载:{
class Stu{
public:
Stu(int n, char *name);
Stu();
...
private:
...
};
注释:无参构造函数和带默认参数的构造函数重载时 可能产生二义性
}
#include<iostream>
#include <cstring>
using namespace std;
class Student{
private:
char *stu_name;
char *stu_no;
float stu_score;
public:
Student(char *name1, char *no1, float score1);
~Student();
void modify(float score2);
void stuShow();
};
Student::Student(char *name1, char *no1, float score1)
{
stu_name = new char[strlen(name1)+1];
strcpy(stu_name, name1);
stu_no = new char[strlen(no1)+1];
strcpy(stu_no, no1);
stu_score = score1;
}
Student::~Student()
{
delete []stu_name;
delete []stu_no;
}
void Student::modify(float score2)
{
stu_score = score2;
}
void Student::stuShow()
{
cout << "The name of student is: " << stu_name << endl;
cout << "The number of student is: " << stu_no << endl;
cout << "The score of student is: " << stu_score << endl;
}
int main()
{
Student stu1("Tom", "2019001", 95.5);
// stu1.stuShow();
stu1.modify(100);
stu1.stuShow();
return 0;
}
拷贝构造函数:{
拷贝构造函数是一种特殊的构造函数 其形参是本类对象的引用 用于将一个已有的对象去初始化另一个新的对象
每个类必须有一个拷贝构造函数 若没有定义 则系统自动生成一个默认的拷贝构造函数 用于复制与数据成员值完全相同的新对象
格式:
类名::类名(const 类名 &对象名)
{
// 拷贝构造函数体
}
调用拷贝构造的形式如下:
类名 对象2(对象1);
类名 对象2 = 对象1;
eg:{
class Score{
public:
Score(int mid, int fin); // 构造函数
Score();
Score(const Score &s); // 拷贝构造函数
~Score(); // 析构函数
...
private:
int mid_exam;
...
};
Score::Score(int mid, int fin)
{
mid_exam = mid;
...
}
Score::Score(const Score &s)
{
mid_exam = s.mid_exam;
...
}
int main()
{
Score s1(80, 90);
Score s2(s1); // 调用拷贝构造函数
Score s3 = sc2; // 调用拷贝构造函数
return 0;
}
}
}
深拷贝与浅拷贝:{
浅拷贝 由默认的拷贝构造函数所实现的数据成员逐一赋值
若类中含有指针类型数据 则浅拷贝的两个对象将指向同一块内存 那么系统调用析构函数后将导致同一空间多次释放而产生错误
}
}
自引用指针'this': {
this 指针保存当前对象的地址
eg:{
void Sample::copy(Sample &s)
{
if(this == &s)
return;
*this = s;
}
}
}
对象数组与对象指针:{
对象数组:{
类名 数组名(元素个数);
eg:{
用只有一个参数的构造函数给对象数组赋值
Exam ob[4] = {89, 90, 91, 92};
用不带参数和一个带参数的构造函数给对象数组赋值
Exam ob[4] = {91, 92};
用带多个参数的构造函数给对象数组赋值
Score ob[3] = {Score{80, 90}, Score{70, 80}, Score{60, 70}};
}
}
对象指针:{
对象指针就是用于存放对象地址的变量 其形式如下:
类名 *对象指针变量名;
eg:{
Score score;
Score *p = &score;
p->成员函数名();
}
}
用对象指针访问对象数组
eg:{
Score score[2];
score[0].setScore(80, 90);
score[1].setScore(70, 80);
Score *p ;
P = score;
p->showScore();
p++;
p->showScore();
Score *p1 = &score[1]; // 指向score[1]的指针
}
}
#include <iostream>
#include <cstring>
using namespace std;
class Stu{
public:
Stu(char *stu_name, int stu_age);
~Stu();
Stu(const Stu& s);
void show_stu(void);
private:
char *name;
int age;
};
Stu::Stu(char *stu_name, int stu_age)
{
name = new char[strlen(stu_name)+1];
strcpy(name, stu_name);
age = stu_age;
}
Stu::~Stu()
{
delete []name;
}
Stu::Stu(const Stu& s)
{
name = new char[strlen(s.name)+1];
strcpy(name, s.name);
age = s.age;
}
void Stu::show_stu(void)
{
cout << "The name of student is: " << name << endl;
cout << "The age of student is: " << age << endl;
}
int main()
{
Stu s1("Tom", 18);
// s1.show_stu();
Stu s2(s1);
s2.show_stu();
// s2.age = 19; // error: age is a private member of class Stu
return 0;
}
string 类{
头文件 #include <string>
常用string类运算符 : = + += == != > >= < <= [](下标) >> <<
eg:{
string s1; // 默认初始化,s1为空字符串
string s2(s1); // s2是s1的副本,等价于 s2 = s1
string s3("value"); // s3是字面值"value"的副本(除字面值最后那个空字符外),等价于 s3 = "value"
string s4(n, 'c'); // 把s4初始化为连续n个字符c组成的字符串 等价于string s4 = string(n, 'c')
}
注释:使用等号(=)初始化一个变量, 则是拷贝初始化, 反之为直接初始化
'getline' 读取一行:
eg:{
string s;
getline(cin, s); // 从标准输入读取一行到字符串s中 直到遇到换行符为止
}
'empty' 判断字符串是否为空:
eg:{
string s1;
if(s1.empty()) // 判断是否为空行
cout << "s1 is empty" << endl;
}
'size' 获取字符串长度:
eg:{
string s2("I am still stuck in the rain");
auto len = s2.size(); // 获取字符串长度 len 的类型是 string::size_type
}
注释: 一条表达式中若有了size()函数 则不需要使用int 避免混用int和unsigned
'ispunct' 判断是否为标点符号:
eg:{
string s3("my hair is still wet");
if(ispunct(s3[0]))
cout << "s3[0] is a punctuation" << endl;
}
'toupper' 转换为大写:
eg:{
string s4("Under mount fuji");
toupper(s4[6]); // 将s4[6]转换为大写
toupper(s4); // 将字符串s4转换为大写
}
字符串string与字面值 (字符串字面值与string是不同类型)
eg:{
string s1 = "your trace are still with me";
string s2 = "like dust without measure"
string s3 = s1 + s2; // 字符串相加
string s4 = s1 + "like dust without measure" // 字符串字面值相加
string s5 = "like dust" + "without measure" // error: 字面值不可相加
}
}
#include <iostream>
#include <string>
using namespace std;
int main()
{
string str1 = "hello myself";
string str2("my name is zozo");
string str3 = str1 + " " + str2;
cout << " " << str3 << endl;
str2 += str2;
str3 += " off";
cout << " " << str2 << endl;
cout << " " << str3 << endl;
cout << "str == str1 ? " << (str1 == str2) << endl;
cout << "str!= str1 ? " << (str1!= str2) << endl;
cout << "str < str1 ? " << (str1 < str2) << endl;
cout << "str > str1 ? " << (str1 > str2) << endl;
return 0;
}
向函数传递对象:{
对象作为函数参数 (不影响实参本身)
对象指针作为函数参数 (将影响实参对象的值)
对象引用作为函数参数 (普遍应用)
}
#include <iostream>
using namespace std;
class Point{
public:
int x;
int y;
Point(int x1, int y1):x(x1), y(y1)
{}
int distance()
{
return x*x + y*y;
}
};
void print_distance(Point p1) // 使用对象作为函数参数
{
p1.x += 1;
p1.y -= 1;
}
void change_point1(Point *p) // 使用对象指针作为函数参数
{
p->x += 1;
p->y -= 1;
}
void change_point(Point& p) // 使用引用作为函数参数
{
p.x += 1;
p.y -= 1;
}
int main()
{
Point point[3] = {Point(1, 2), Point(3, 4), Point(5, 6)};
Point *p = point;
print_distance(*p);
cout << "The distance of point1 is: " << p[0].distance() << endl;
p++;
change_point1(p);
cout << "The distance of point2 is: " << p->distance() << endl;
change_point(point[2]);
cout << "The distance of point3 is: " << point[2].distance() << endl;
return 0;
}
静态成员:{ 关键字 'static'
静态数据成员:{
无论建立多少类的对象 都仅有一个静态数据成员的拷贝 所有对象共享同一份静态数据
需在类外且定义对象前 单独初始化
形式如下 : static 数据类型 数据成员名;
访问格式:
类名::静态数据成员名;
对象名.静态数据成员名;
对象指针->静态数据成员名;
}
静态成员函数:{
静态成员函数属于整个类 是该类所有对象共享的成员函数
静态成员函数的作用: 处理静态数据成员
静态成员函数限定为内部连接 私有静态成员函数不被类外部函数和对象访问
形式如下: static 返回值类型 静态成员函数名(参数表);
访问格式:
类名::静态成员函数名(参数表); //(常用形式)
对象名.静态成员函数名(参数表);
对象指针->静态成员函数名(参数表);
}
}
#include <iostream>
using namespace std;
class Score{
private:
int mid_exam;
int fin_exam;
static int count;
static float sum;
static float ave; // 静态成员变量
public:
Score(int m, int f);
~Score();
static void show_count_sum_ave(); // 静态成员函数
};
Score::Score(int m, int f)
{
mid_exam = m;
fin_exam = f;
count++;
sum += fin_exam;
ave = sum / count;
}
Score::~Score()
{
}
/* 静态成员初始化 */
int Score::count = 0;
float Score::sum = 0;
float Score::ave = 0;
void Score::show_count_sum_ave()
{
cout << "The count of scores is: " << count << endl;
cout << "The sum of scores is: " << sum << endl;
cout << "The average of scores is: " << ave << endl;
}
int main()
{
Score sco[3] = {Score(80, 90), Score(70, 80), Score(90, 95)};
sco[1].show_count_sum_ave();
Score::show_count_sum_ave();
return 0;
}
友元:{ 关键字 'friend'
包括友元函数和友元类
用于对私有或保护成员进行访问
友元函数:{
可以是不属于任何类的非成员函数 也可以是另一个类的成员函数 可访问该类的所有成员
将非成员函数声明为友元函数
eg:{
class A{
public:
A(int x);
friend int getA(A &a);
...
private:
int Bb;
};
int getA(A &a)
{
return a.Bb;
}
}
}
友元类:{
将一个类声明为另一个类的友元
class Y{
...
};
class X{
friend Y; // 声明Y为X的友元类
};
}
友元关系不具备'交换性'和'传递性'
}
类的组合:{
在一个类中内嵌另一个类的对象作为数据成员 称为类的组合 该内嵌对象称为对象成员 又称子对象
class A{
...
};
class B{
A a; // 内嵌A对象作为数据成员
...
};
}
共享数据的保护:{
常引用 const 类型& 引用名
eg:{
int a = 5;
const int &b = a; // 此时b的值就不能被修改了
int add(const int &m,, const int &n)
{
return m+n;
}
//此函数中m和n都是常引用 不能被修改
}
常对象:{
类名 const 对象名(参数表);
const Date date(2021,1,1);
常对象成员:{
常数据成员 使用const修饰
若一个类中声明了常数据成员 则构造函数只能通过成员初始化列表来初始化该常数据成员 其他函数不能改变该值
}
常成员函数:{
形式如下: 类名 函数名(参数表) const;
eg:{
calss Date{
public:
Date(int year, int month, int day);
int getYear() const; // 常成员函数
...
private:
int Dyear;
int Dmonth;
int Dday;
};
Date::Date(int year, int month, int day) : Dyear(year), Dmonth(month), Dday(day)
{ }
int Date::getYear() const // 常成员函数
{
...
}
const可被用于对重载函数区分
}
}
注释:常成员函数可以访问常数据成员 也可访问普通数据成员
常对象只能调用它的常成员函数 不能调用它的普通成员函数 常成员函数是常对象唯一对外的接口
}
}
}
#include <iostream>
#include <string>
using namespace std;
class Score; // 提前声明Score类以便引用
class Student{
private:
string name;
int number;
public:
Student(string na, int num)
{
name = na;
number = num;
}
friend void show_score(Score &sc, Student &st); // 声明show_score为友元函数
};
class Score{
private:
int mid_exam;
int fin_exam;
public:
Score(int m, int f)
{
mid_exam = m;
fin_exam = f;
}
friend void show_score(Score &sc, Student &st); // 声明show_score为友元函数
};
void show_score(Score &sc, Student &st)
{
cout << "The name of student is: " << st.name << "student number is: " << st.number << endl;
cout << "The mid_exam score is: " << sc.mid_exam << " fin_exam score is: " << sc.fin_exam << endl;
}
int main()
{
Score sco1(80, 90);
Student st("Tom", 20101);
show_score(sco1, st);
return 0;
}