类和类之间关系
- A has B:包含关系,类B已经是类A的数据成员。
- A uses B:拥有关系,类A中的部分函数使用了类B,可能是通过友元或者函数参数建立联系。
- A is B :继承关系,具有传递性。
耦合度:is > has > uses ,面向对象追求的最高境界:高类聚、低耦合
继承
简单例子
student.h
#include "stdafx.h"
#include <iostream>
#include <string>
using namespace std;
class Student
{
public:
Student(int id, string name) :m_id(id), m_name(name) {}
void Print()
{
cout << "name: " << m_name << " id: " << m_id ;
}
private:
int m_id;
string m_name;
};
class Student_New :Student
{
public:
Student_New(int id, string name, int score) :Student(id, name),m_score(score) //通过父类的构造函数
{
}
void Print()
{
Student::Print();
cout << "score: " << endl;
}
private:
int m_score;
};
int main()
{
Student_New s1(1, "julian", 90);
s1.Print();
return 0;
}
注意:子类虽然继承于父类,但是当各自创建对象的时候,子类对象和父类对象之间内存空间是独立的,两者之间互不干扰。
继承时子类构造与析构过程
- 子类构造如果不使用父类的有参构造,会默认先调用父类的无参构造函数(如果没提供则报错)
- 子类在结束的时候先析构自己,再调父类的析构函数
子类有和父类同名变量
- 如果在父类是private类型,则子类只能通过父 类的成员函数访问
- 如果在父类是public类型,则子类直接访问的是自己的,通过 父类:: 访问父类的同名变量
继承中的static变量
- 父类有static变量,子类也共享,但是子类定义static变量,父类无法访问。
继承方式
父类是public | 父类是protected | 父类是private | |
---|---|---|---|
public继承 | 儿子是:public | protected | 不可见 |
protected继承 | protected | protected | 不可见 |
private继承 | private | private | 不可见 |
注意:一般写代码用共有(public)继承比较多,剩下两个很少用。
类的赋值兼容性原则
1. 子类对象可以直接赋值给父类对象或者接初始化父类对象,反之不行
2. 父类指针可以直接指向子类对象,反之不行(重要)
3. 父类引用可以直接引用子类对象,反之不行
class Student
{
public:
void Print1()
{
cout << " Student" << endl;
}
private:
int m_id;
};
class Student_New : public Student
{
public:
void Print()
{
cout << "New Student" << endl;
}
private:
int m_score;
};
int main()
{
//1. 赋值
Student_New s1,s3;
Student s2 = s1;//子类初始化父类
s2 = s3; //子类赋值给父类
//指针
Student* p;
p=&s1; //父类指针可以接受子类地址,然后干父类的事
//引用
Student& p=s1;
p.Print1();
return 0;
}
多继承与虚继承(c++特有)
多继承简单例子
class Sofa
{
public:
Sofa()
{
cout << "Sofa constructor" << endl;
}
void Print()
{
cout << " Sofa" << endl;
}
~Sofa()
{
cout << "Sofa destructor " << endl;
}
};
class Bed
{
public:
Bed()
{
cout << "Bed constructor" << endl;
}
void Print()
{
cout << "Bed" << endl;
}
~Bed()
{
cout << "Bed destructor" << endl;
}
};
class SofaBed:public Sofa,public Bed
{
public:
void Print()
{
Sofa::Print();
Bed::Print();
}
};
int main()
{
SofaBed a;
a.Print();
return 0;
}
结果:定义一个 SofaBed,继承Sofa和Bed类,构造顺序和析构顺序:
虚继承
- 在多继承下有一个问题:如果上面例子的Sofa和Bed都继承另一个Furniture类,Furniture类有成员变量 材质:m,那么Sofa和Bed继承于它,则各有一个m,这个时候,SofaBed继承于Sofa和Bed,那么SofaBed将会有两个材质m,造成歧义,一个沙发床要求只有一个材质m。
解决:在Sofa和Bed继承的时候加上 virtual关键字,代表虚继承,这时候SofaBed继承于Sofa和Bed,那么SofaBed将会有一个材质m(来于Furniture)。如图: