1.继承关系
1.1概述:
什么叫继承呢?简单来说:就是老子的东西,都会被儿子继承下来。
(除了构造函数,是不会被继承的(GNUg++编译是这样的,VS有点不同))
1.2.继承关系的用意和目的是什么?
老子的特有属性都被儿子继承了下来,所以儿子类中是不是就可以不用再写父类中的属性与方法了。这样就提高了代码的复用性。
同时儿子类中我们还可以添加一些儿子类独有的新特性。这样就提高了代码的拓展性。
所以说继承关系的用意是:代码复用性与高拓展性。就如同这个缤纷复杂的世界,我们可以找到很多的现实的例子。
使用继承关系,需要同学们看待这个世界的事物要上升一个维度,要具有一些抽象的思维。
首先要把这一类的事件进行抽象出来一些共有的属性与特征,把它们定义为父类。然后,再用这个父类,对具有不同特点的子类进行派生。这样就可以派生出各种不同的子类。子类不仅拥有父类的共有的特性,与具备子类独用的特性。这样的代码的复用性与拓展性就会非常灵活。
2.继承关系在C++中的语法形式:
单继承的方式:
class + 子类 : 继承方式 + 父类
{
//单继承的方式
};
多继承的方式:
class + 子类 : 继承方式 + 父类1,继承方式 + 父类2,继承方式 + 父类3,...
{
//多继承的方式
};
3.继承方式:
继承方式有三种:
public:公有继承
protected:受保护继承
private:私有继承
当继承方式与类中访问权限的结合时,类内属性到子类之中的访问权限的改变如图所示:
继承实例代码演示:
#include <iostream>
using namespace std;
class Car
{
private:
int weight;
public:
Car()
{
cout << "Car的构造" << endl;
}
~Car()
{
cout << "Car的析构" << endl;
}
void run()
{
cout << "车子正在行驶之中" << endl;
}
int setWeight(int weight)
{
this->weight = weight;
}
};
class BWM : public Car
{
private:
string logo;
public:
BWM()
{
cout << "宝马的构造" << endl;
}
BWM(string logo,int weight)
{
this->logo = logo;
this->setWeight(weight);
cout << "宝马的有参构造" << endl;
}
~BWM()
{
cout << "宝马的析构" << endl;
}
void happyCry()
{
cout << "你的女朋友幸福地流下的眼泪" << endl;
}
};
class BNZ : public Car
{
private:
string logo;
public:
BNZ(string logo)
{
this->logo = logo;
cout << "奔驰的有参构造" << endl;
}
~BNZ()
{
cout << "奔驰的析构" << endl;
}
void upCry()
{
cout << "在奔驰车顶伤心的流下的眼泪" << endl;
}
};
int main()
{
// cout << sizeof(Car) << endl;
// cout << sizeof(BWM) << endl;
BWM bmw;
// bmw.run();
// bmw.happyCry();
// BNZ bnz("bnz");
// bnz.upCry();
// bnz.run();
return 0;
}
4.单继承关系的内存布局:
子类在定义对象时,先创建子类的空间,然后构造顺序是:先调用父类的构造对父类中的属性完成初始化,然后再调用子类的构造完成对子类属性的初始化。
当子类对象被销毁时,析构的顺序是:首先调用子类的析构,然后再调用父类的析构,最后资源就被回收了。
5.当使用继承时,如果父类中没有默认构造,需要在子类的初始化列表指定编译器所应该调用父类构造。
#include <iostream>
using namespace std;
class Car
{
private:
int weight;
public:
Car(int weight)
{
this->weight = weight;
cout << this << endl;
cout << "Car的构造" << endl;
}
~Car()
{
cout << "Car的析构" << endl;
}
void run()
{
cout << "车子正在行驶之中" << endl;
}
int setWeight(int weight)
{
this->weight = weight;
}
};
class BWM : public Car
{
private:
string logo;
public:
//当父类中没有默认构造时。
//在子类的初始化列表中指定编译器调用那个构造来完成父类中的属性的初始化。
BWM():Car(1)
{
cout << this << endl;
cout << "宝马的构造" << endl;
}
BWM(string logo,int weight):Car(1)
{
this->logo = logo;
this->setWeight(weight);
cout << "宝马的有参构造" << endl;
}
~BWM()
{
cout << "宝马的析构" << endl;
}
void happyCry()
{
cout << "你的女朋友幸福地流下的眼泪" << endl;
}
};
int main()
{
// cout << sizeof(Car) << endl;
// cout << sizeof(BWM) << endl;
BWM bmw;
// bmw.run();
// bmw.happyCry();
return 0;
}
6.当父类中有与子类中的属性或方法同名时,父类中的同名属性或方法,将被自动隐藏在父类的类域之中。
#include <iostream>
using namespace std;
class Car
{
public:
int weight = 1000;
public:
Car()
{
cout << "Car的构造" << endl;
}
~Car()
{
cout << "Car的析构" << endl;
}
void run()
{
cout << "车子正在行驶之中" << endl;
}
void setWeight(int weight)
{
this->weight = weight;
}
};
class BWM : public Car
{
public:
string logo;
int weight = 2000;
public:
BWM()
{
cout << "宝马的构造" << endl;
}
~BWM()
{
cout << "宝马的析构" << endl;
}
void happyCry()
{
cout << "你的女朋友幸福地流下的眼泪" << endl;
}
void run()
{
cout << "宝马车正在高速行驶" << endl;
}
};
int main()
{
BWM bmw;
cout << bmw.weight << endl;
cout << bmw.Car::weight << endl;
bmw.run();
bmw.Car::run();
return 0;
}
访问同名变量分为静态变量和非静态变量
继承非静态变量成员处理方式
和上述例程是一样的,
访问子类的直接通过子类对象访问,如bmw.weight,这时子类继承父类的同名属性被隐藏,如需访问加上域名访问, bmw.Car::weight。
继承同名静态变量成员处理方式
#include <iostream>
using namespace std;
class Base {
public:
static int m_A;
};
class Son : public Base
{
public:
static int m_A;
};
1、通过对象访问 // 同名静态属性 类内声明 类外初始化
Son s;
cout<<"son 下的m_A ="<<s.m_A<<endl;
cout<<"Base 下的m_A ="<<s.Base::m_A<<endl;
2、通过类名访问
cout<<"son 下的m_A ="<<Son ::m_A<<endl;
cout<<"Base 下的m_A ="<<Son::Base::m_A<<endl;
//第一个::代表类名访问,第二个代表父类作用域下的
函数也是如此访问