对于c语言有常用的数据类型(int,string等)以及自定义数据类型,自定义数据类型只能用结构体定义,而且结构体只能存放常用的数据类型,想实现具体的方法必须在结构体外提供接口
对于c++,自定义数据类型除了用结构体定义,还可以用类定义,class里封装了函数给用户提供接口
封装实现的是保护内部,接口就是为了与外部进行交互
类和类之间产生关系:OOP/OOD
- Composition (复合)
- Delegation (委托)
- Inheritance (继承)
1. 复合(Composition)
我有一个你,比如容器 queue 里拥有 deque
构造由内而外
Container的构造函数首先调用Component的默认构造函数,然後才执行自己。
析构由外而内
Container的析构函数首先执行自己,然后才调用Component的析构函数。
2. 委托(Composition by reference)
我有一个你,但没有完全有 (/狗头)
比如在一个类A中定义一个指针,指针B是另外实现的一个类,所以只有在创建对象时,A才真正拥有B,A与B不同步
3. 继承
是一种的关系,比如人是一种哺乳动物,子类可以继承父类所有的公有资产,copy一份父类data,但成员函数的继承可以理解为子类可以调用父类的函数。
//父类中所有非静态成员属性都会被子类继承下去
//父类中私有成员属性是被编译器给隐藏了,因此是访问不到,但是确实被继承下去了
一般对于父类的属性用protected属性,这样子类在public继承后还是protected属性
对于父类用protected继承后,共有和保护属性全变保护了,这样子类必须重新提供接口才能访问到属性
对于父类用private继承后,后面就啥也访问不到了(丁克)
构造由内而外
Derived 的构造函数首先调用 Base 的默认构造函数,然後才执行自己。
析构由外而内
Derived 的析构函数首先执行自己,然后才调用 Base 的析构函数。
4. 虚函数 (动态多态)
类中的成员函数大致可以分为三种:
- non-virtual 函数 : derived class不能重新定义(override,覆写)
- virtual 函数︰derived class 可以重新定义(override,覆写)它 , 且你对它已有默认定义
- pure virtual 函数 ∶ derived class 必须(override)覆写它, 而且你对它没有默认定义。
如果一个类中包含纯虚函数,那这个类就叫抽象类,抽象类的父类不能实例化对象,可以理解成行业标准
构造函数不需要定义为虚函数,析构函数必须定义为虚函数。
静态多态, 函数地址早绑定,编译阶段就确定了函数地址
class Animal
{
public:
void speak() { cout << "动物在说话" << endl; }
};
class Cat :public Animal
{
public:
void speak() { cout << "小猫在说话" << endl; }
};
class Dog :public Animal
{
public:
void speak(){ cout << "小狗在说话" << endl; }
};
void DoSpeak(Animal & animal)
{
animal.speak();
}
int main() {
Cat cat;
DoSpeak(cat); //输出是动物在说话
Dog dog;
DoSpeak(dog); //输出是动物在说话
system("pause");
return 0;
}
动态多态 virtual
虚函数只能通过父类引用或者指针来指向子类对象,对于纯虚函数的基类不能实例化对象
//Animal animal
class Animal
{
public:
//Speak()就是虚函数
virtual void speak() { cout << "动物在说话" << endl; }
};
class Cat :public Animal
{
public:
void speak() { cout << "小猫在说话" << endl; }
};
class Dog :public Animal
{
public:
void speak(){ cout << "小狗在说话" << endl; }
};
void DoSpeak(Animal & animal)
{
animal.speak();
}
//多态满足条件:
//1、有继承关系
//2、子类重写父类中的虚函数
//多态使用:父类指针或引用指向子类对象
int main() {
Cat cat;
DoSpeak(cat); //输出小猫在说话
Dog dog;
DoSpeak(dog); //输出小狗在说话
system("pause");
return 0;
}
——————设计模式——————
5. 虚函数与继承
//继承与虚函数
#include <iostream>
using namespace std;
class CDocument
{
public:
void onFileOpen ()
{
cout << "dialog..." << endl;
cout << "check file status..." << endl;
cout << "open file..." << endl;
serialize () ;
cout <<"close file..." <<endl;
cout <<"update all views. .." <<endl;
}
virtual void serialize () { };
};
class CMyDoc : public CDocument{
public:
virtual void serialize (){
//只有应用程序本身才知道如何读取自己的文件(格式)
cout << "CMyDoc::Serialize() " << endl;
}
};
int main ()
{
CMyDoc myDoc; //假设对应[File / Open]
myDoc.OnFileOpen();
}
6. 继承与复合
6.1 复合是在子类中
![ZWLSLVPSOX`}D8WU7XEQVT.png
#include<iostream>
using namespace std;
class B
{
public:
B() { cout << "B的构造函数" << endl; }
~B() { cout << "B的析构函数" << endl; }
};
class A
{
public:
A() { cout << "A的构造函数" << endl; }
~A() { cout << "A的析构函数" << endl; }
};
class C : public A
{
public:
C() { cout << "C的构造函数" << endl; }
~C() { cout << "C的析构函数" << endl; }
public:
B b;
};
void test01()
{
C c;
}
int main()
{
test01();
system("pause");
return 0;
}
不知道这个为啥是B->A->C,但在vs里运行的就是这个结果。感觉应该是A->B->C
6.2 复合是在父类中
#include<iostream>
using namespace std;
class B
{
public:
B() { cout << "B的构造函数" << endl; }
~B() { cout << "B的析构函数" << endl; }
};
class A
{
public:
A() { cout << "A的构造函数" << endl; }
~A() { cout << "A的析构函数" << endl; }
public:
B b;
};
class C : public A
{
public:
C() { cout << "C的构造函数" << endl; }
~C() { cout << "C的析构函数" << endl; }
};
void test02()
{
C c;
}
int main()
{
test02();
system("pause");
return 0;
}
7. 继承与委托(功能最强大)
1.
2.文件系统
3.
源码实现
8. pointer like classes
9. function like classes
class中含有重载的 操作符()