C++学习笔记
类和对象(一)
1. C语言和C++语言的区别:C语言是面向过程的语言,C++是面向对象的语言。
2. C++(面向对象)的三大核心概念:封装、继承、多态 + C++标准新特性(命名空间
namespace string)、STL(vector、list、map)。
3. C语言的结构体和C++的类的区别:C语言结构体成员的默认访问权限为共有,而C++的成员的默
认权限为私有。
4. 封装:a. 把变量和函数写在一个类中,实现封装 b. 把不想暴露在外界的成员私有化private;
封装性把数据与操作数据的函数组织在一起,不仅是程序结构更加紧凑,并且提高了类内
部数据的安全性。
继承:子类继承父类的成员,代码复用;继承性增强了软件的可扩充性以及代码重用性。
多态:父类的指针或引用有多种的表现形态,用父类的指针或引用统一操作各种子类对象。
多态性使设计人员在设计程序时可以 对问题进行更好的抽象,有利于代码的维护和可
重用。
5. 两种编程思想:面向过程的语言(C语言),面向对象的语言(C++,Java,Objective-C)。
6. 面向过程的编程通常把程序分为三个步骤:(1)、输入数据 (2) 、计算 (3)、输出结果
7. 类与对象的关系总结:类是对象的抽象类型,对象是类的具体实例,如人是张三的类型,张三是
一个具体的人,因此说人是类型,张三是具体的一个对象。
8. 编程工具: (1)、vc++6.0; (2)、 vs; (3)、xcode;
9. C++的类通常由两个部分组成:(1) 成员变量 一般是私有的; (2) 成员函数—操作成员
变量的 一般公有的。
10. 成员函数的实现可以直接在类内部实现或在类外部实现但是要在每一个函数名前加类名作用域
符号,void Point::setX(float a)。
11. 声明类的时候一般类名首写字母大写,如class Point{}、 class Person{}等。
12. 构造函数是一种比较特殊的成员函数,用于创建并初始化对象。声明对象时构造函数会被编译
器自动调用。
构造函数的四个特点:
(1)、构造函数的访问权限必须是公有(public);
(2)、构造函数名和类名相同;
(3)、构造函数没有返回值;
(4)、构造函数可以带参数,用于初始化成员变量。
13. 默认构造函数分两种:1.构造函数不带参数;2.构造函数带参数但参数都有默认值。
默认构造函数时指在声明对象时,可以不传递参数,使用空值或默认值对对象进行初始化,而普
通构造函数在声明对象是必须传递参数(实参),否则构造函数的参数(形参)没有值,编译出
错。
类和对象(二)
14. 函数重载的概念:在同一个作用域中,可以有一组具有相同函数名,不同参数列表的函数,这
组函数被称为重载函数。参数列表不同是指参数的个数或参数的类型不同,如:
void f();
void f(int x);
void f(int x, int y);
如果仅仅是函数的返回值类型不同,不能是函数的重载:
void f(int x);
int f(int x);
这两个函数不是函数的重载,在同一个作用域内是不能共存的,因为在函数调用时不知道该调用
哪一个函数。
15. (1) 类中可以定义多个构造函数,但是必须能够构成函数重载;
(2)声明对象时的参数类型和个数要与构造函数的参数进行匹配。
16. 构造函数中对类的成员变量两种初始化的方式:
第一种方法:在构造函数体内通过赋值语句初始化
Thing(int a,int b,int c){x=a;y=b;z=c;}
第二种方法:使用初始化列表形式初始化
Thing(int a,int b,it c):x(a),y(b),z©{ }
程序中使用初始化列表的三个原因:
(1)、对于类类型的成员,使用初始化列表效率更高;
(2)、有些类型的成员变量必须使用初始化列表的形式初始化。如const成员、引用成员;
(3)、在继承时,子类的构造函数中初始化父类的成员时。
17. 复合类:也叫做组合类,是指将一个类的对象作为另一个类的成员变量。
#include<iostream>
using namespace std;
//类和对象:类的对象相当于数据类型的变量
//(用户自定义类型)Point p; (系统预定义)int a;
class Point
{
public:
Point();//默认构造函数
Point(float _x,float _y);//普通构造函数
void print();//打印函数
private:
float x;
float y;
};
Point::Point() {}
Point::Point(float _x, float _y) //类的作用域
{
x = _x;
y = _y;
}
void Point::print()
{
cout << "(" <<x<< "," << y<<")" << endl;
}
//-----------------------------------------------------------分隔线------------------------------------------------------------------------
class Circle //复合类,组合类:一个类包含另一个类的对象
{
public:
Circle();
Circle(float x, float y, float r);
void setCircle(float r, Point p);//修改圆的半径和圆心点
void print();
private:
Point center;//center.x center.y
float radius;
};
Circle::Circle(){}
//构造函数中需要显式地使用初始化列表初始化center
//否则编译器会自动调用Point类中的默认构造对其进行初始化;
Circle::Circle(float x, float y, float r) :center(x, y), radius(r) {}
void Circle::setCircle(float r, Point p)
{
radius = r;
center = p;
}
void Circle::print()
{
cout << "radius:" << radius << endl;
center.print();
}
int main()
{
Point p(5, 7);
p.print();
Circle c;
c.setCircle(1, p);
c.print();
return 0;
}
- 析构函数:创建对象时系统会自动调用构造函数进行初始化工作,同样,销毁对象时系统也会
自动调用一个函数来进行清理工作(回收对象占用的内存空间),这个函数被称为析构函
数。
析构函数(Destructor)也是一种特殊的成员函数,没有返回值,不需要用户调用,而是在
销毁对象时自动执行。与构造函数不同的是,析构函数的名字是类名前面加一个"~"符号,
e.g:~Circle();
析构函数的四个特点:
(1) 没有返回值;
(2) 无参;
(3) 不能被重载(唯一);
(4) 必须公有。
如果类中有指针成员变量,并且指针指向堆空间,那么程序员必须显示地声明析构函数,释放指针指向的堆空间,避免内存泄漏。
析构函数示例:
#include<iostream>
using namespace std;
class Test
{
public:
Test() { cout << "HelloWorld!\n"; }
~Test() { cout << "GoodBye world!\n"; }
};
int main()
{
Test t;//创建时调用构造函数
//对象被销毁时会自动调用析构函数
return 0;
}
析构函数必须存在的情况:
#include<iostream>
using namespace std;
class Test
{
public:
Test();
~Test();
private:
int* _pVar;//1.类中包括指针成员变量
};
Test::Test()
{
_pVar = new int[10];//2.指针指向堆空间
cout << "Hello World" << endl;
}
Test::~Test()
{
if (_pVar)
{
delete []_pVar;
_pVar = NULL;
}
cout << "Goodbye World" << endl;
}
int main()
{
Test t;//创建时调用构造函数
//对象被销毁时会自动调用析构函数
return 0;
}
类和对象(三)
19.类和对象的使用:和结构体一样,一个类的对象也可以以值、指针或者引用的形式作为函数的参
数或返回值。一般情况下,为了避免创建临时对象通常传对象的引用,并且为了避免在函数体内修
改对象的值,通常使用常引用。
const Point middle(const Point& p1, const Point& p2);
如果函数以传值形式返回一个类的对象,编译器会创建一个临时对象来保存这个值。
但有些编译器会做优化。
20.浅拷贝:可以把一个对象赋值给另外一个对象,对象的每个成员的值,将一对一的拷贝到新的对
象。这种拷贝叫做逻辑拷贝,或浅拷贝。但是,如果对象含有指针成员变量,而指针变量又指向
堆上空间,将只拷贝指针成员变量本身的值,造成两个对象的指针指向同一块堆上的内存空间,删
除对象时造成二次删除。
21.const关键字:const是c/c++中保留的一个关键字,它用来限定一个变量是只读的,即不可变得。 程序中使用const可以在一定程度上提高程序的健壮性。
const关键的作用:
(1) const定义常量,const float pi=3.14;其值不能被改变;
(2) const与指针,常量指针和指针常量;
(3) const与函数,const int func(const int &a)const;
a.修饰形参时,形参不能被修改
b.修饰成员函数时,函数体内不能修改成员变量的值。
(4) const对象const Point p; 常量对象
const对象只能调用const成员函数,不能调用普通成员函数。
普通对象既可以调用const成员函数,也可以调用普通成员函数。
22.this指针:每一个对象都“包含”一个指针指向对象自身,称之为this指针。
当对象调用成员函数时,会默认将对象自身传递给该函数,在函数体内不直接使用对象名,
而是使用this指针,即this指针,即this指针指向对象,指向调用者
#include <iostream>
using namespace std;
class Circle
{
public:
Circle()
{
radius = 10.0;
x_center = 0.0;
y_center = 0.0;
}
void printRadiusOnly()
{
cout << "r:" << radius << endl;
cout << "r:" << this->radius << endl;
cout << "r:" << (*this).radius << endl;
cout << this << endl;
}
private:
float radius;
float x_center;
float y_center;
};
int main(int argc, char**argv)
{
Circle c1;
c1.printRadiusOnly();
Circle c2;
c2.printRadiusOnly();
cout << &c1 << endl;
cin.get();
}
23.静态局部变量:函数结束后,静态局部变量的内存空间不会被系统回收,下一次调用函数时使用
上一次退出时的值。
(1) 静态局部变量存储在静态存储区;
(2) 静态局部变量在函数结束后内存空间不会被回收,下次使用时可以保留上一次的计算结果,这
与全局变量很相似;
(3) 静态局部变量如果未进行初始化,会被编译器初始化为0或NULL;
24.静态全局变量:静态全局变量只能在它所声明的文件中使用,不能被extern关键字引用;
静态全局变量与全局变量的区别:生命周期不变,作用域会减小。
25.类的静态成员变量与非静态成员变量的区别:
每一个对象都会为它的非静态成员变量在内存中保留一块空间来存储各自的值,而对于类的静态
成员变量整个类中只有一份拷贝,所有的对象都共享这块空间。
类的静态成员的访问:
方式一:类名::静态成员名 Student::teacherName;
方式二:对象名.静态成员名 Student s1; s1.teacherName;
推荐使用方式一来访问,因为静态成员属于整个类,而不是某一个特定的对象。
类的静态成员变量必须在类外使用类名+作用域符号进行初始化,如:
char *Student::teacherName="";
静态成员函数只能访问静态成员,不能访问非静态成员,普通函数既可以访问静态成员也可以
访问非静态成员。
#include <iostream>
using namespace std;
void show_average(double x)
{
static double num = 0;
static double sum = 0;
num += 1;
sum += x;
cout << "num = " << num << ","<<"sum = "<<sum <<","<< "avg = " << sum / num << endl;
}
int main(int argc, char const *argv[])
{
double entry = 0;
for (; ; )
{
cout << "Enter a number: ";
cin >> entry;
if (entry < 0) break;
show_average(entry);
}
return 0;
}
26.友元函数可以访问类的私有成员,但是注意友元函数不是类的成员函数。一个类也可以作为另一
个类的友元类,也就意味着这个类中所有的成员函数时另一个类的友元函数。
#include <iostream>
using namespace std;
class Point
{
//友元函数
friend Point middle(const Point &p1, const Point &p2);
public:
Point(float a, float b) :x(a), y(b){}
void print()
{
cout << "("<<x << "," << y<<")" << endl;
}
private:
float x;
float y;
};
//需求:写一个函数求两个点的中点
//类外的一个普通函数,不能直接用对象名,去访问私有
Point middle(const Point &p1, const Point &p2)
{
Point mp((p1.x + p2.x) / 2, (p1.y + p2.y) / 2);
return mp;
}
int main(int argc, char const *argv[])
{
Point p(1, 1);
Point q(2, 2);
middle(p, q).print();
return 0;
}