继承的概念:
继承就是在一个已经存在的类的基础上建立一个新的类,并拥有其特性。
继承是面向对象的三大特性之一,体现了代码复用的思想。
已经存在的类被称为“基类”或“父类”
新建立的类被称为“派生类”或“子类”
派生类除了可以继承基类外,还可以对其做出必要的代码修改(函数隐藏)和增加
注意:
基类与派生类是相对的,一个类既可以作为基类,又可以作为派生类,取决于两个两类之间的相对关系。基类通常更加抽象,派生类通常更加具体
代码示例:
#include <iostream>
using namespace std;
class Father //基类
{
public:
string first_name = "张";
void work()
{
cout << "我是一个木匠" << endl;
}
};
class Son:public Father //派生类
{
public:
void work() // 函数隐藏
{
cout << "我是一个程序员" << endl;
}
void play() // 新增函数
{
cout << "我喜欢打游戏" << endl;
}
};
int main()
{
Son s;
cout << s.first_name << endl;
s.work();
// 通过类名::调用基类被隐藏的函数
s.Father::work();
s.play();
return 0;
}
继承中的构造函数:
(1)基类与派生类构造函数的关系
类的构造函数和析构函数不能被继承,派生类的所有构造函数都必须直接或间接调用基类的任一一个构造函数
代码示例:
#include <iostream>
using namespace std;
class Father
{
private:
string first_name;
public:
Father(string fn="王"):first_name(fn){}
Father() // 手动补充一个无参构造
{
cout << "Father" << endl;
}
void set_first_name(string fn)
{
first_name = fn;
}
string get_first_name() const
{
return first_name;
}
};
class Son:public Father
{
public:
// Son类没有编写构造函数,编译器会自动添加一个无参的构造函数
// 在无参构造函数中调用基类的无参构造参数
// 如果基类没有无参构造函数,可以使用两种已学的方法解决
// 1. 【函数重载】给基类一个手写的无参构造函数
// 2. 【默认参数】给基类有参构造设置参数的默认值
};
int main()
{
Son s;
cout << s.get_first_name() << endl;
s.set_first_name("王");
cout << s.get_first_name() << endl;
return 0;
}
(2)派生类调用基类的构造函数:
派生类也可以通过编写代码的方式直接或间接调用基类的任意一个构造函数,有三种方法
(1)透传构造
透传构造指的是在派生类的构造函数中直接调用基类的构造函数
代码示例:
#include <iostream>
using namespace std;
class Father
{
private:
string name;
int age;
public:
Father(string name,int age)
{
this->name = name;
this->age = age;
}
void show()
{
cout << name << " " << age << endl;
}
};
class Son:public Father
{
public:
// 透传构造
Son(string name,int age):Father(name,age)
{
}
// 透传构造
Son():Father("佚名",100)
{
}
};
int main()
{
Son s("张三",12);
s.show();
Son s2;
s2.show();
return 0;
}
(2)委托构造
委托构造指的是同一个类的构造函数可以调用这个类的另一个构造函数,通过委托构造可以让派生类中的构造函数间接调用基类的构造函数
代码示例:
#include <iostream>
using namespace std;
class Father
{
private:
string name;
int age;
public:
Father(string name,int age)
{
this->name = name;
this->age = age;
}
void show()
{
cout << name << " " << age << endl;
}
};
class Son:public Father
{
public:
// 透传构造
Son(string name,int age):Father(name,age)
{
}
// 委托构造
Son():Son("佚名",100)
{
}
};
int main()
{
Son s("张三",12);
s.show();
Son s2;
s2.show();
return 0;
}
(3)继承构造
继承构造并不是继承了构造函数,在C++11中,可以通过继承构造的语法,让派生类自动实现每个基类的构造函数,并且同样参数的构造函数进行透传
代码示例:
#include <iostream>
using namespace std;
class Father
{
private:
string name;
int age;
public:
Father(string name,int age)
{
cout << "Father的构造函数调用了" << endl;
this->name = name;
this->age = age;
}
void show()
{
cout << name << " " << age << endl;
}
};
class Son:public Father
{
public:
// 基类有几个重载的构造函数,派生类就自动添加几个
// 每个派生类的构造函数都去透传调用同样参数格式的基类构造函数
using Father::Father;
// 在本例中,Son类会创建一个两个参数的构造函数,透传调用基类的构造函数
};
int main()
{
Son s("张三",12);
s.show();
return 0;
}
(3)对象的创建与销毁流程
代码示例:
#include <iostream>
using namespace std;
/**
* @brief The Value class 作为其它类的变量
*/
class Value
{
private:
string name;
public:
Value(string name):name(name)
{
cout << name << "创建了" << endl;
}
~Value()
{
cout << name << "销毁了" << endl;
}
};
class Father
{
public:
static Value s_value;
Value value = Value("Father类的成员变量");
Father()
{
cout << "Father类的构造函数" << endl;
}
~Father()
{
cout << "Father类的析构函数" << endl;
}
};
Value Father::s_value = Value("Father类的静态成员变量");
class Son:public Father
{
public:
static Value s_value;
Value value = Value("Son类的成员变量");
Son()
{
cout << "Son类的构造函数" << endl;
}
~Son()
{
cout << "Son类的析构函数" << endl;
}
};
Value Son::s_value = Value("Son类的静态成员变量");
int main()
{
cout << "-----------主函数开始执行-----------" << endl;
// 局部代码块
{
Son s;
cout << "----------对象使用中----------" << endl;
}
cout << "-----------主函数结束执行-----------" << endl;
return 0;
}
代码的运行结果如下:

观察上述结果,可以得到一些规律:
(1)对象使用之前是创建流程,对象使用后是销毁流程,创建与销毁的流程是对称的。
(2)静态成员的创建比非静态成员更早,静态成员的销毁比非静态成员的销毁更晚。
(3)基类部分比派生类部分先创建,基类部分比派生类部分后销毁。
继承的权限问题:
(1)公有继承
在公有继承的情况下,派生类继承的基类成员中:
(1)基类的私有成员无法直接访问
(2)基类的保护成员与公有成员在派生类中仍然做为派生类的保护成员与公有成员,权限不变
代码示例:
#include <iostream>
using namespace std;
class Father
{
public:
string str1 = "公有成员";
protected:
string str2 = "保护成员";
private:
string str3 = "私有成员";
};
class Son:public Father
{
public:
Son()
{
cout << str1 << endl;
cout << str2 << endl;
// cout << str3 << endl; 错误
}
};
class Grandson:public Son
{
public:
Grandson()
{
cout << str1 << endl;
cout << str2 << endl;
// cout << str3 << endl; 错误
}
};
int main()
{
Son s;
cout << s.str1 << endl;
// cout << s.str2 << endl; 错误
// cout << s.str3 << endl; 错误
return 0;
}
(2)保护继承
在保护继承的情况下,派生类继承的基类成员中:
(1)基类的私有成员无法直接访问
(2)基类的保护成员与公有成员在派生类中都作为派生类的保护成员
代码示例:
#include <iostream>
using namespace std;
class Father
{
public:
string str1 = "公有成员";
protected:
string str2 = "保护成员";
private:
string str3 = "私有成员";
};
class Son:protected Father
{
public:
Son()
{
cout << str1 << endl;
cout << str2 << endl;
// cout << str3 << endl; 错误
}
};
class Grandson:public Son
{
public:
Grandson()
{
cout << str1 << endl;
cout << str2 << endl;
// cout << str3 << endl; 错误
}
};
int main()
{
Son s;
// cout << s.str1 << endl; 错误
// cout << s.str2 << endl; 错误
// cout << s.str3 << endl; 错误
return 0;
}
(3)私有继承
在私有继承的情况下,派生类继承的基类成员中:
(1)基类的私有成员无法直接访问
(2)基类的保护成员与公有成员在派生类中都作为派生类的私有成员
继承中不写权限,默认为私有继承
代码示例:
#include <iostream>
using namespace std;
class Father
{
public:
string str1 = "公有成员";
protected:
string str2 = "保护成员";
private:
string str3 = "私有成员";
};
class Son:private Father
{
public:
Son()
{
cout << str1 << endl;
cout << str2 << endl;
// cout << str3 << endl; 错误
}
};
class Grandson:public Son
{
public:
Grandson()
{
// cout << str1 << endl; 错误
// cout << str2 << endl; 错误
// cout << str3 << endl; 错误
}
};
int main()
{
Son s;
// cout << s.str1 << endl; 错误
// cout << s.str2 << endl; 错误
// cout << s.str3 << endl; 错误
return 0;
}