文档库 最新最全的文档下载
当前位置:文档库 › c++笔记

c++笔记

第一天
引用
int &b = a;//创建引用类型变量时,要立刻 "赋值"

(1)引用是变量的别名, 不会再开辟空间
(2)引用在实计开发中,只使用于函数的形式参数
(3)比喻: 引用是一种受限指针
(4)引用能做的事指针都能做,而指针能做事引用不一定能用。
(5)引用的底层实现多数编译器也是指针.
(6)引用初始化后,以后都不能再次被重新赋值
例如:
#include
using namespace std;

void f1() {
int a = 20;
int &b = a;//创建引用类型变量时,要立刻 "赋值"
cout<cout<cout<<&a<cout<<&b<}
void f1(int &r) {//int &r = age
r = 22; //age=22
}

int main() {
f1(age);
cout<<"age="<return 0;
}


类与对象
具体到某个具体的事物就是对象,没有具体到单一的事物就是类
比如,地球就是对象,恒星就是类。

一个对象可以有多个类,这些类是包含关系
比如,某人是一个男人,男人是一个动物,男人属于动物

class Stu {
public:
int age;//成员变量
int no;
string name;
void sleep() {//成员函数
cout<<"sleep()"<}

Stu stu1;//age no name //创建Stu类的对象
Stu stu2;//age no name

stu1.age = 10;//访问成员: “对象.成员”
stu1.no = 1;
https://www.wendangku.net/doc/8717194358.html, = "小明";



函数重载
函数名一样,通过参数的不同来区分

构造函数
构造函数名必须与类名相同


第二天

常成员变量
1.常成员变量是用关键字const来声明成员变量,const位于变量前或类型前都一样
2.常成员变量只能通过构造函数的初始化表对常成员变量进行初始化
3.常成员变量所在类中所有构造函数都必须通过初始化表对常成员变量进行初始化
4.常成员变量可以像普通成员一样被访问,但是其值不能被修改
class Time {
public:
const int hours;
int cons minute;
Time();
......
}

Time::Time():hours(1),minute(2) {
}


常成员函数
常成员函数不能被修改对象,即不能修改对象的成员变量
常成员函数:用const来修饰的成员函数,const位于函数的括号之后,定义和声明的地方都要加上const
常成员函数不能修改成员变量的值
常成员函数只能调用常成员函数,不能调用普通成员函数
普通成员函数可以调用常成员函数

声明:class Time {
public:
void show()const;
......
}

定义:void Time::show() const
{
......
}

常对象
定义形式:1. 类名 const 对象名(实参列表)
2. const 类名 对象名(实参列表)

常对象中所有的成员变量的值都是不能被修改
常对象访问函数时只能访问

常成员函数
定义创建对象的时候把所有成员变量赋值(初始化),根据参数选择调用哪个构造函数
例:const Stu stu1(1,2);

const Time time1;
Time const time2;
const Time time3(100);
Time const time4(200);

对象的动态创建和销毁
new可以动态创建对象,创建后会返回对象的地址,如果内存不够创建失败,返回一个0指针值
用delete销毁对象

例如:
Teacher *p = new Teacher;
delete p;

//黑技术
Teacher *p = (Teacher *)malloc(sizeof(Teacher));
p->show();
delete p;
用malloc创建不会调用构造函数,但会调用析构函数

对象的赋值
class Stu {
public:
int age;
int no;
......
};


Stu stu1;
stu1.age=30;stu1.no=100;
Stu stu2;
stu2=stu1;//对象的赋值

Stu stu3=stu1;//对象的复制
Stu stu4(stu1);//对象的复制
对象的复制只调用一次构造函数,调用两次析构函数,实际调用了两次构造函数,只是看见一次

静态成员变量(static)
静态成员变量在项目运行时就分配内存(和c语言一样),项目运行结束以后才销毁
静态成员变量必须在类体外初始化,建议放在main函数所在文件中
格式为:
类名::静态成员变量=初值
int Stu:: a =20;

静态成员函数
声明函数时,使用static修饰就可以了
Class Box {
static int volume();
}

访问静态成员函数的方式:
1.与普通成员函数被访问方式一样,可以用对象指针和引用来访问
2.静态成员函数所属类类名::静态成员函数
静态成员函数中没有 “this”

static修饰的成员可以像普通的成员一样被访问(指针,对象,引用)
static成员函数中不能通过this访问普通成员
普通的函数可以通过this访问静态成员,也可能通过类名::访问静态成员

访问权限修饰符
public:公有 成员在任何位置可被访问
protected:受保护 成员在当前类与子类中可被访问
private:私有 成员在当前类中可被访问

当前类指:定义类那一部分,包括类中函数的定义部分

只改变使用域,不改变内存分配

第三天
继承与派生
继承可以解决代码的重复使用

公马,母马继承了马,马派生了公马,母马
马是基类,公马,母马是派生类

派生类可以向基类对象赋值。

单继承:一个派生类只从一个基类派生
多重继承:一个派生类不仅可以从一个基类派生,也可以从多个基类派生。
一个派生类有两个或多个基类。

派生类的声明形式:
class 派生类名:[继承方式] 基类名1,......,[继承方式] 基类名n {
派生类新增加的成员
};

继承方式包括:public, private,protected.
如果不写继承方式,则默认为private(私有的)


单基继承
假如有A类,然后让B类公有继承A类
class B:pulic A {
......


多基继承
假如有A类,B类,C类,让D类公有继承A类,公有继承B类,私有继承C类
class D:public A,public B,private C {
......
}

派生类的构成
派生类的成员包括从基类继承过来的成员和自己的新增加的成员(成员指成员变量和成员函数)

派生类不能吸收构造函数和析构函数


基类成员权限修饰类与继承方式对继承的作用
public 继承下来的成员权限不变
受保护的继承下来全是受保护的
私有的继承下来全是私有的

派生类的构造函数和析构函数
1.构造函数和析构函数都不能被继承
2.派生类对象被创建时,基类对象会被先创建
3.派生类的构造函数被调用时,会先调用基类的其中一个构造函数
4.派生类的构造函数中用了初始化表的方式调用了基类构造函数,默认不写时调用了基类中可以不传参数的构造函数
5.在派生类对象被释放时,先执行派生类析构函数,再执行基类析构函数

class A {
public:
A();
A(int x);
~A();
};


class B:public A {
public:
int x;
B();
B(int x);
~B();
};

B::B():A(),X(123) {
......
};

B::B(int y):A(y) {
......
};


多基继承的二义性
如果以及声明了类A1,A2,再让B继承A1和A2,如果A1,A2中有同名字的成员,
并且多被B继承下去了,此时使用B的对象访问同名字的成员会产生二义性。


虚基派生:共同基类产生的二义性的解决方法。
如果有相同名字的成员,则只取一个。

基类与派生类的转换
基类声明的指针变量和引用类型变量可以指向派生类的对象
class B::public A {......}
B b;
A *pa=&b;
A &ra=b;

1.当使用对象的指针变量去访问对象的成员时,能访问到的成员只有从指针所属类中的继承下来的成员。
2.当使用对象的引用类型变量去访问对象的成员时,能访问到的成员只有从指针所属类中的继承下来的成员。

派生类的内存是新增加的变量追加到继承下来的变量的后面,所以还是同一地址,
使用指针变量和引用时,看是什么类型的指针,决定偏移量是多少(个人观点)


继承与组合
实际开发中,多用组合,少用继承

在B类中以A类的对象作为成员变量,称为类的组合。(对象作为成员变量就是类的组合)

例如:
class A {......};
class B {......};

class C {
public:
A a;
B b;
......
};

初始化表的总结:
1.为成员变量赋值
2.指定基类的构造函数
3.指定组合类的构造函数

如果类C继承A类,组合B类,那么当创建C类对象时

,调用构造函数的顺序是:A-B-C (继承先创建成员变量,再创建对象)

第四天
多态性是指具有不同功能的函数可以用同一个函数名,这样就可以用一个函数名调用不同内容的函数。
面向对象中一般这样表述多态性:向不同的对象发送同一消息,不同的对象在接受时会产生不同的行为(即方法)。

从系统实现的角度看,多态性分为:静态多态性和动态多态性。

确定调用的对象的过程称为关联(binding),在这里是指把一个函数名与一个类的对象捆绑在一起,建立关联。
一般来说,关联是把一个标识符和一个存储地址联系起来。

重写:派生类的成员函数与基类的成员函数的名字相同,参数相同,并且返回类型相同或可以类型兼容,则称为派生类重写了基类函数,简称重写。


隐藏:派生类中的成员函数与基类中的成员函数名字相同,派生类的成员函数会屏蔽基类中的同名的成员函数。
派生类中的成员变量与基类中的成员变量同名时,派生类的成员会屏蔽基类中的同名的成员变量。
通过派生类对象,指针,或引用 访问基类中被隐藏的成员时,要在成员前面加上“基类名::”
重写是隐藏的一种。

被隐藏了就访问不到了。

虚函数:在声明函数时,在最前面加上virtual,则该函数就是虚函数(一般用于重写,回调),基类的虚函数被派生类继承后仍是虚函数。
派生类中可以重写基类的虚函数。

用指针访问重写的虚函数时,被访问的虚函数是指针指向的对象所属类中的虚函数(只看指向的对象所属的类)。
而用指针访问重写的普通函数时,被访问的函数是指针类型所属类的函数(只看指针是什么类)。

对象指针:
访问普通函数,只看指针类型
访问虚函数,只看指针的值。

虚析构函数:
虚析构函数即:定义声明析构函数前加virtual修饰,如果将基类的析构函数声明为虚析构函数时,
由该基类所派生的所有派生类的析构函数也都自动成为虚析构函数。


基类指针指向用new动态创建的派生类对象child时,用delete删除,删除对象分为两种情况。
第一.如果基类中的析构函数为虚析构函数,则会先删除派生类对象,再删除基类对象。
第二.如果基类中的析构函数为非虚构函数,则只会删除基类对象,不会删除派生类对象,这样便出现了内存泄漏。

纯虚函数:没有函数体,不用定义。
声明纯虚函数一般形式: virtual 函数类型 函数名(参数列表)=0;
最后的“=0”并不表示函数返回值为0,它只起形式上的作用,告诉编译系统“

这就是纯虚函数”‘

抽象类:
包含一个或者一个以上纯虚函数的类就是抽象类。

不能用抽象类创建对象,但是可以用抽象类派生出派生类,也可以用抽象类创建指针和引用来指向抽象类的派生类对象。
抽象类的派生类可以把抽象类中成员变量和成员函数继承下来,包括纯虚函数也会被继承。

纯虚函数被派生类实现以后即为虚函数。


什么时候用组合?
什么时候用继承?
什么时候用重写?
什么时候用抽象?

组合就是部分与整体,但是不是本质上的,比如电脑和键盘,键盘就不是本质上的,cpu就是。
继承就是把所有都有的,共同的部分写在一起,然后继承,解决代码的重复使用。
当对继承下来的功能不满意,就用重写。(实际开发中一定是重写虚函数,重写普通函数没有意义)

不重写就不使用虚函数,不重写使用虚函数没有意义。

派生类继承下来的函数都不满意时,就用抽象类。


构造函数的访问权限修饰符
public修饰的构造函数可以在任何位置创建对象调用。
protected修饰的构造函数只能被当前类或子类中创建对象。
private修饰的构造函数只能被当前类创建对象调用。


名称空间:


相关文档