第一章 面向对象程序设计概述
面向对象的语言
:类
:钟表。(本质特征:都是看时间)对象(类的实例)
:某块特定的钟表。(颜色、形状等可能不一样)类
:分类的主要依据:抽象。例如:石头、汽车、树木等都是人们长期的生产生活中抽象出来的概念。类与对象的关系
:犹如模具与铸件的关系,一个属于某类的对象称为该类的一个示例。封装
:尽可能简化内部细节。对外形成一个边界,只保留有限的对外接口使之可以与外部发生反应。例如:sort函数就是一个封装好的函数,直接输入地址就可以对数组进行排序。继承
:特殊类拥有一般类的全部属性与服务,我们称为特殊类对一般类的继承。例如:轮船是一般类,客船是特殊类。(a是一般类,如果b有a全部属性特点,在此基础上,b还有特殊的属性,那么b就是特殊类。)源程序
:还没翻译的代码。(机器无法识别)目标程序
:源程序经过翻译生成的程序,可以直接执行。翻译程序
:汇编程序
:将汇编语言写的源程序翻译成目标程序。(高级语言用不到)编译程序
:将高级语言写的源程序翻译成目标程序。(C、C++)解释程序
:与编译程序的不同点:编译程序一次性将汇编程序翻译完,解释程序翻译一句、执行一句,反复进行。(JAVA、BASIC)程序的开发过程
:(C++为例)1.编辑
:将源程序输入到计算机中,生成后缀为cpp的磁盘文件。2.编译
:将程序的源代码转换为机器语言代码。3.连接
:将多个源程序文件以及库中的某些文件连接在一起,生成一个后缀为exe的可执行文件。4.运行调试
。第二章 面向对象程序设计基础
cin和cout基本输入和输出
:getline(cin,str):输入带空格字符串。常变量的定义
:const 变量类型 变量名=x(所定义的变量为常量)引用与常引用
:(对一块地址重复命名) int n = 10;
int &a = n; //引用
const int &b = n; //常引用
cout << a << ' ' << b << endl;
内联函数
:系统直接将调用内联函数的地方用等价的语句替换,减少运行环境的保存和恢复时间。(在函数名前面加上inline即是内联函数,但是内联函数只适合小功能的函数,例如一个计算公式等)带缺省值的函数
:预先给定形参值,如果不给定实参值,则采用形参值。函数重载
:多个 参数数量 或参数类型 不同的函数 函数名相同动态内存分配
(注意:返回的是分配的空间的首地址) int *p, *q;
p = new int(3);//初始化该空间的值为3
q = new int;
delete[] p;
delete[] q;
int *p, *q;
p = new int[10]; //分配10个int型的元素,把该内存的首地址给p
q = new int;
delete[] p;
delete[] q;
动态内存的释放
:delete int *p, *q;
p = new int[10];
q = new int;
delete[] p; //多个元素的动态内存释放
delete q; //单个元素的动态内存释放
第三章 类和对象(一)
c++面对对象程序设计,也使用了类和对象的概念,并通过下面的方法来模拟对象的状态和行为:
- 1.对象的状态通过对象的属性数据来描述。
- 2.对象的行为:定义一个函数集,通过调用对应函数表示对象完成一个行为。
类
:由成员变量(数据成员)和成员函数组成对象的定义
:类名 对象名(形如int a、double a)。对象的访问
: class student
{
public:
int score;
string name;
void change_score(int a)
{
score = a;
}
void change_name(string a)
{
name = a;
}
};
int main()
{
student a;
a.change_score(100);
a.change_name("hesor");
cout << a.name << ' ' << a.score << endl;
return 0;
}
/*
Output:
hesor 100
*/
构造函数
:主要用来初始化对象的数据成员,构造函数可以重载。构造函数没有函数返回类型,且函数名与类名相同。代码示例
:class student
{
public:
int score;
string name;
student()
{
score = 10;
name = "orz";
}
student(int s, string n)
{
score = s;
name = n;
}
void change_score(int a)
{
score = a;
}
void change_name(string a)
{
name = a;
}
};
int main()
{
//调用无参构造函数 注意:不是student a()
student a;
student b(100, "hesor");
cout << a.name << ' ' << a.score << endl;
cout << b.name << ' ' << b.score << endl;
return 0;
}
/*
Output:
orz 10
hesor 100
*/
类的访问控制
:public
:公有成员,在程序的任何地方都可以访问。一般作为类与外界的接口。private
:私有成员,只能被该类的成员函数或该类的友元访问。protect
:保护成员,与私有成员差不多,主要在继承方面有区别,(派生类可以访问基类的保护成员,但是不能访问基类的私有成员)。析构函数
:析构函数和构造函数类似,不过构造函数是在创建对象的时候自动调用,而析构函数是在销毁对象的时候程序自动调用。但是析构函数需在函数名前加上~,并且析构函数没有参数(因此析构函数不能重载)。拷贝构造函数
:一种特殊的构造函数,用一个已存在对象来初始化正在创建的新对象。类的继承
:A类继承B类,B叫做基类,A叫做派生类(也叫做父类与子类)。class student : public person
{
};
派生类构造函数
:class person
{
public:
string name;
int high;
person(string a, int h)
{
name = a;
high = h;
}
};
class student : public person
{
public:
int score;
// student(int a) //1
// 如果采用 1 这种派生类的构造函数,那么基类默认使用无参构造函数初始化从基类继承的成员
student(int a) : person("hesor", 170) //派生类构造函数
{
score = a;
}
};
main()
{
student a(100);
cout << a.name << ' ' << a.score << ' ' << a.high << endl;
return 0;
}
/*
Output:
hesor 100 170
*/
派生类构造函数
:与基类构造函数一样,但是需要注意一点:派生类析构函数调用的时候基类中的析构函数也会调用!class person
{
public:
string name;
int high;
person(string a, int h)
{
name = a;
high = h;
}
~person()
{
cout << "基类 end... ..." << endl;
}
};
class student : public person
{
public:
int score;
// student(int a) //1
// 如果采用 1 这种派生类的构造函数,那么基类默认使用无参构造函数初始化基类成员变量
student(int a) : person("hesor", 170) //派生类构造函数
{
score = a;
}
~student()
{
cout << "派生类 end... ..." << endl;
}
};
main()
{
student a(100);
cout << a.name << ' ' << a.score << ' ' << a.high << endl;
return 0;
}
/*
Output:
hesor 100 170
派生类 end... ...
基类 end... ...
*/
函数重定义
:派生类对基类中继承过来的函数进行重新定义(要求函数返回值、参数个数、参数类型完全一致)。class person
{
public:
void f()
{
cout << "基类" << endl;
}
};
class student : public person
{
public:
void f()
{
cout << "派生类" << endl;
}
};
main()
{
student a;
person b;
a.f();
b.f();
return 0;
}
/*
Output:
派生类
基类
*/
多重继承下的派生类的定义
:class student
{
public:
void f_student()
{
cout << "我是学生" << endl;
}
};
class teacher
{
public:
void f_teacher()
{
cout << "我是老师" << endl;
}
};
class student_teacher : public student, public teacher
{
};
main()
{
student_teacher a;
a.f_student();
a.f_teacher();
return 0;
}
/*
Output:
我是学生
我是老师
*/
多重继承中的二义性问题
:由于多重继承有多个基类,基类的属性名和方法名可能重复,所以派生类中会产生二义性问题。例如下图,若A有成员变量name,BC继承了A之后 都会有变量 name,然后 D又多重继承了BC,那么D就会有两个name变量,调用的时候就会产生二义性。解决方法
:class person
{
public:
int NUM = 123456;
};
class student : public person
{
};
class teacher : public person
{
};
class student_teacher : public student, public teacher
{
};
main()
{
student_teacher a;
cout << a.teacher::NUM;
return 0;
}
/*
Output:
123456
*/
虚拟继承
:加入virtual关键字,将图中的A类定义为虚基类,虚基类的成员在类的继承关系中只会被继承一次。class person
{
public:
int NUM = 123456;
};
class student : virtual public person
{
};
class teacher : virtual public person
{
};
class student_teacher : public student, public teacher
{
};
main()
{
student_teacher a;
cout << a.NUM;
return 0;
}
/*
Output:
123456
*/