【BUAA-OO】pre学习笔记
发表于:2022-10-21 | 分类: BUAA面向对象
字数统计: 2.1k | 阅读时长: 9分钟 | 阅读量:

上ly老师的OOPre课所做的一些笔记,用cpp为载体比较系统的讲解了面向对象的三大特征(封装、继承、多态),可以作为了解这方面知识的开始,但记录较为繁杂,我后续会持续做整理补充。

课堂笔记

Pre

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
//A better C

#include "iostream"
using namespace std;

//array, pointer,function,struct,macro
struct Node{
int data;
struct Node *next;
};
//封装
//#progma pack(1)
struct Test{
int i;
double d;
int j;//内存对齐
char ch:1;//位结构
};
//统一控制宏,#define 。。。
//#ifdef ... #else ... #endif

/*c++调用c函数
extern "C"{
void md5();
}

*/


/*函数重载overloading
void print(int);
void print(char*);

*/
/*default parameter
void fun(int a,int b,int c=3);
*/

//exception处理 throw(int),抛出异常

//类中的参数可以用不传地址的函数修改,原理是用了this指针

int main(int argc,char *argv[]){

}

// 堆区栈区

//static&extern

0913

  • 堆区栈区:堆区:malloc new的空间

  • static:

    • 一次构造和全局变量一起析构;
    • 只能本文件使用,链接器链接不到;
    • 类里,用于共享内存,不能在构造函数初始化;
    • 类中函数static修饰后,可以直接用类名调用
  • 总结: static把对象的变量变成了类的变量
  • extern链接器指令
    • 全局函数自带extern
  • 声明vs定义
  • 引用,安全版指针,消除了两个问题,野指针问题和半路指岔
    如何理解向上转型和多态,多态的触发条件是重写

0920

  • 设计模式
1
2
3
4
class Single{
private:
static
}
  • 如何构造一个对象
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
class Test{
private:
int i;
int *p;
public:
Test(int,int);
~Test();
}
Test t1(1,2);
Test t2(t1); //拷贝构造(clone),深拷贝、浅拷贝
//会崩溃,浅拷贝只拷贝了指针地址,而同一块空间不能delete两次.
//所以不能clone指针
//下面是深拷贝
class Test{
private:
int i;
int *p;
public:
Test(int,int);
Test(const Test &t);
~Test();
}
Test::Test(const Test &t){
this->i = t.i;
//this->p = t.p;
this -> p = new Test(*t.p);
}
Test t1(1,2);
Test t2(t1);
//使用指针的常见错误
/*
* 1. 野指针
* 2. 内存泄漏
* 3. 重复释放
* 4. 返回局部变量的地址
* 5. 类似浅拷贝
*/
//free
//free(p);
if(p!=NULL){
free(p);
p=NULL;
}
//4
int *fun(){
int a=10;
return &a;
}//不可重现错误,a的内存没有再分配那就还是10
int *fun(){
int *p = new int(10);
return p;
}//解决上一个问题,但是有新问题,p不记得delete
void fun(){

}
//5
memcpy()浅拷贝
clone()和putAll()都是只对于built_in类型深克隆

  • C追求的是运行的高效,java追求的是编程的高效

  • 继承

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// inheritance
class A {

}
class A2 extends A{

}

//implement
interface A {

}
class A2 implements A{

}

  • const
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
const double pi = 3.14;

//const与函数返回值的关系
const int fun(){

}
cout << fun()++ << endl;
//error:fun()是l-value,常量;
//对于built-in type有效(如 int)
//但对于自定义类型

//传参pass by value vs pass by address(pointer & reference)
//功能 read vs read/write
//性能 低效(sizeof obj) vs 高效(sizeof int)
//其他 可能是拷贝构造 vs nothing
//never passby value(对于自定义变量)

//对于拷贝构造
const Test &t //这样传参可以保证函数对t只读

//const对于类
const Test t;
t.fun() //error: 编译器认为你可能在fun里改变自己的内存
//所以得这样
class Test {
public:
void fun () const ;
}

0927

  • 操作符重写
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
class Account{
int id;
string name;
int balance;
public:
Account(int id, int balance);
Account& operator+(int money);
Account& operator++();
Account operator++(int); //硬传参
}
Account& Account::operator+(int money){
this.balance += money;
return *this;
}
Account Account::operator++(int){
Account a(*this);
this -> balance++
return a;
}
Account& Account::operator++(){
this -> balance ++;
return *this;
}

int main(){
Account a(1,100);
a = a + 1;
}
  • new/delete
1
2
3
4
//new vs malloc
//new = malloc + construct
//delete = destruct + free #注意顺序 delete解决申请的内存,free 解决申请内存的内存
//new是一个operator, 可以重写, 可以避免内存碎片化
  • 继承
1
2
3
4
5
6
7
8
9
10
11
12
13
class Student{
int cardId;
char *name;
//history
public:
void BorrowBook();
}
class Teacher{
int cardId;
char *name;
...
}
//继承就是共性与特性
  • 子类对父类的重写
1
2
3
super.fun1();//java
Base::fun1();//C++
//如果在子类中重写了父类的函数,98%的可能会出现super
  • cpp可以多重继承
    • 所以不能使用super
  • 不能菱形继承

1004

  • 子类的构造会调用父类的构造
  • 析构同样
  • 注意顺序
1
2
3
4
5
6
7
8
9
class Test {
public:
int i;
int j;
Test(int m);
}
Test::Test(int m): j(m),i(j){ //这里会先定义i,再给j赋值,按定义的顺序

}

多态

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
//reuse
class Pet{
public:
int i;
virtual void speak(); //虚函数,多态和后绑定 later binding 的必要条件
virtual void sleep(); //而且无论多少个虚函数一共占4byte(virtual table这是针对于类的,和对象没关系),virtual关键字自动继承
}
void Pet :: speak(){
cout << "Pet::speak" << endl;
}
class Cat: public Pet{
public:
void speak();
}
void Cat :: speak(){
cout<< "miaomiao" << endl;
}
void handle(Pet &pet){ // never pass by value
pet.speak();
//...
}
int main(){
Cat cat; //upcasting,向上类型转换,所以子类不要削弱父类的接口。
handle(cat); //???
}

//binding:将一次函数调用与函数入口相对性的一致
//代码区,函数(代码),常量,lib
//全局变量区:包括static,一次初始化,最后析构
//runtime memory:
//1. stack
//2. heap
//early binding
//later binding / runtime binding / dynamic binding
//有指针就没有private
  • 多态的实现
    • 虚函数表
    • 虚指针
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
//函数的类型
//constructor: 构造不会用虚函数,不会有多态。
//destructor:
class Test{
public:
Test();
virtual ~Test(); //这里需要多态,如果没有,在delete p时只会调~Test
}
class Derived: public Test{
public:
Derived();
~Derived();
}
void fun(Test *p){
//...
delete p;
}
int main(){
Derived *derived = new Derived;
fun(derived);
}
  • 高级抽象!
1
2
3
4
5
6
7
8
//抽象的越高级,就越无法描述
//所以
virtual void speak(){/*...*/};
virtual void speak() = 0; //pure virtual(纯虚函数);
//一个类里面有一个纯虚函数,就是abstract class。
//抽象类不可被实例化,但可以被继承,子类通常要对其进行override,没有全部override的话,就是个半抽象
//纯虚函数可以有函数体,但通常没有
//抽象的作用:祖训,提纲挈领
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
//串联(c++里叫抽象类,而java里叫interface)
//java不可以有多继承,但是可以实现多个接口(interface没有属性)
class FlyObject{
public:
virtual void fly() = 0 ;
}
class Animal{

}
class Bird : public Animal . public FlyObject{
public:
void fly();
}

class Machine{

}
class Airplane : public Machine . public FlyObject{
public:
void fly();
}

void follow(Bird &bird){ //follow(FlyObject &fO)
bird.fly(); //由于行为的共性,变得相关
//...
}
  • 代码重用的另一个拷贝形式
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
class Stack{
int pool[100];
int top;
public:
Stack();
int pop();
void push(int a);
}
Stack::Stack() :top(0){

}
int Stack::pop(){
return pool[--top];
}
void Stack::push(int a){
pool[top++] = a;
}
int main(){
Stack S;
for(int i = 0; i < 10; i++)
push(i*i);
for(int i = 0; i < 10; i++)
cout << pop() << endl;
}
//如果要一个double的stack呢;
//constainer 容器
//模板类
template <class T>
class Stack{
T pool[100];
//...
}
int main(){
Stack<int> intStack;
Stack<double> doubleStack;
}
//c++里有STL(standard template library)
//C++与java的区别:java有类库,自成体系,跨平台(用java runtime)
//C++与操作系统有关
#include <vector> //动态增长的万能容器
using namespace std;
int main(int argc, char *argv[]){
vector<int> v;
for(int i=0; i<100000; i++)
v.push_back(i);
cout << v[10034] << endl; //[]运算符重载
}

1018

  • template
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include <vector>
#include <cstdio>
using namespace std; //命名分割,防止命名重复

namespace MyClass{ //一般放在头文件里
class Test{

}
}

int main(){
MyClass::Test test = new();
vector<int> v;
for(i=0; i < 0; i++){
v.push_back(i);
}
//iterator迭代器模式
vector<int>::iterator it = v.begin();
while(it != v.end()){
cout << *it << endl; //这里的*,++也是运算符重载
it++;
}
return 0;
}

课程总结 OO based on cpp

  • 封装
    • struct、class
    • data+function
    • access control(private, public, protest)
    • this
    • construct/destruct stack/heap
    • reference/copy constructor
    • keyWord: static const
  • 继承
    • 共性与特性
    • 多重继承(x)
    • 不要削弱父类接口
    • 构造顺序
  • 多态
    • upcasting,传参
    • runtime binding 前绑定,后绑定
    • vitual v-table v-ptr
    • 高级抽象:抽象类,接口(行为的共性)
    • template
    • 性能问题出现前,不需要考虑性能
  • 真理导向,结果导向

GUI

  • console控制台程序
  • 两类:基于Form, 基于Web

  • win32 application

  • API应用程序开发接口
上一篇:
【BUAA-高代】向量空间与内积空间讲课资料
下一篇:
【BUAA-CO】p2mips常用宏定义