从零开始学C++之继承(一):公有/私有/保护继承、overload/overwrite/override之间的区别
来源:互联网 发布:unpack php 编辑:程序博客网 时间:2024/05/01 06:13
一、继承
C++很重要的一个特征就是代码重用。在C语言中重用代码的方式就是拷贝代码、修改代码。C++可以用继承或组合的方式来重用。通过组合或继承现有的的类来创建新类,而不是重新创建它们。
继承是使用已经编写好的类来创建新类,新的类具有原有类的所有属性和操作,也可以在原有类的基础上作一些修改和增补。
新类称为派生类或子类,原有类称为基类或父类
派生类是基类的具体化
(一)、派生类的声明语法为:
class 派生类名 : 继承方式 基类名
{
派生类新增成员的声明;
}
(二)、公有/私有/保护成员
在关键字public后面声明,它们是类与外部的接口,任何外部函数都可以访问公有类型数据和函数。
在关键字private后面声明,只允许本类中的函数访问,而类外部的任何函数都不能访问。
在关键字protected后面声明,与private类似,其差别表现在继承与派生时对派生类的影响不同
(三)、公有/私有/保护继承
(四)、接口继承与实现继承
我们将类的公有成员函数称为接口。
公有继承,基类的公有成员函数在派生类中仍然是公有的,换句话说是基类的接口成为了派生类的接口,因而将它称为接口继承。
实现继承,对于私有、保护继承,派生类不继承基类的接口。派生类将不再支持基类的公有接口,它希望能重用基类的实现而已,因而将它称为实现继承。
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
using namespace std;
class Base
{
public:
int x_;
protected:
int y_;
private:
int z_;
};
class PublicInherit : public Base
{
public:
void Test()
{
x_ = 10;
y_ = 20;
//z_ = 30; error
}
private:
int a_;
};
class PublicPublicInherit : public PublicInherit
{
public:
void Test()
{
y_ = 20;
}
};
class PrivateInherit : private Base
{
public:
void Test()
{
x_ = 10;
y_ = 20;
//z_ = 30; error
}
};
int main(void)
{
PublicInherit pub;
pub.x_ = 20;
PrivateInherit pri;
//pri.x_ = 10; error
return 0;
}
(五)、继承与重定义
对基类的数据成员的重定义
对基类成员函数的重定义分为两种
overwrite(隐藏)
override(覆盖)
(六)、继承与组合
无论是继承与组合本质上都是把子对象放在新类型中,两者都是使用构造函数的初始化列表去构造这些子对象。
组合通常是在希望新类内部具有已存在的类的功能时使用,而不是希望已存在类作为它的接口。组合通过嵌入一个对象以实现新类的功能,而新类用户看到的是新定义的接口,而不是来自老类的接口。(has-a)
如果希望新类与已存在的类有相同的接口(在这基础上可以增加自己的成员)。这时候需要用继承,也称为子类型化。(is-a)
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
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
using namespace std;
class Base
{
public:
Base() : x_(0), y_(48)
{
}
int GetBaseX() const
{
return x_;
}
int GetBaseY() const
{
return y_;
}
void Show()
{
cout << "Base::Show ..." << endl;
}
int x_;
private:
int y_; //继承后无法被直接访问,可通过GetBaseY访问
};
class Derived : public Base
{
public:
Derived() : x_(0)
{
}
int GetDerivedX() const
{
return x_;
}
void Show(int n)//与下面的show 构成重载,基类的show被隐藏
{
cout << "Derived::Show " << n << endl;
}
void Show()
{
cout << "Derived::Show ..." << endl;
}
int x_; //重定义x_,基类的x_被隐藏
};
//组合关系
class Test
{
public:
Base b_;
int x_;
};
int main(void)
{
Derived d;
d.x_ = 10;
d.Base::x_ = 20; //访问被隐藏的基类x_;
cout << d.GetBaseX() << endl;
cout << d.GetDerivedX() << endl;
cout << d.GetBaseY() << endl;
d.Show();
d.Base::Show();//访问被隐藏的基类show
cout << sizeof(Derived) << endl;
cout << sizeof(Test) << endl;
return 0;
}
下面总结一下overload/overwrite/override 之间的区别:
(1)相同的范围(在同一个类中);
(2)函数名字相同;
(3)参数不同;
(4)virtual关键字可有可无。
覆盖(override)是指派生类函数覆盖基类函数,特征是:
(1)不同的范围(分别位于派生类与基类);
(2)函数名字相同;
(3)参数相同;
(4)基类函数必须有virtual关键字。
隐藏(overwrite)(派生类与基类)
(1)不同的范围(分别位于派生类与基类);
(2)函数名与参数都相同,基类无virtual关键字
(3)函数名相同,参数不同,virtual可有可无
在Java中定义了关键字final,被final修饰的类不能被继承。但在C++中没有final这个关键字,要实现这个要求还是需要花费一些精力。
首先想到的是在C++ 中,子类的构造函数会自动调用父类的构造函数。同样,子类的析构函数也会自动调用父类的析构函数。要想一个类不能被继承,我们只要把它的构造函数和析构函数都定义为私有函数。那么当一个类试图从它那继承的时候,必然会由于试图调用构造函数、析构函数而导致编译错误。
可是这个类的构造函数和析构函数都是私有函数了,我们怎样才能得到该类的实例呢?这难不倒我们,我们可以通过定义静态来创建和释放类的实例。基于这个思路,我们可以写出如下的代码:
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// Define a class which can't be derived from
///////////////////////////////////////////////////////////////////////
class FinalClass1
{
public:
static FinalClass1 *GetInstance()
{
return new FinalClass1;
}
static void DeleteInstance( FinalClass1 *pInstance)
{
delete pInstance;
pInstance = 0;
}
private:
FinalClass1() {}
~FinalClass1() {}
};
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// Define a class which can't be derived from
///////////////////////////////////////////////////////////////////////
template <typename T> class MakeFinal
{
friend T;
private:
MakeFinal() {}
~MakeFinal() {}
};
class FinalClass2 : virtual public MakeFinal<FinalClass2>
{
public:
FinalClass2() {}
~FinalClass2() {}
};
2
3
4
5
6
7
8
9
{
public:
Try() {}
~Try() {}
};
Try temp;
参考:
C++ primer 第四版
Effective C++ 3rd
C++编程规范
- 从零开始学C++之继承(一):公有/私有/保护继承、overload/overwrite/override之间的区别
- 从零开始学C++之继承(一):公有/私有/保护继承、overload/overwrite/override之间的区别
- 从零开始学C++之继承(一):公有/私有/保护继承、overload/overwrite/override之间的区别
- 公有继承、私有继承和保护继承之间的对比
- 公有、私有、保护继承的区别
- c++:私有继承,公有继承,保护继承
- C++的公有继承,私有继承,保护继承的区别
- C++中公有继承、保护继承、私有继承的区别
- C++中公有继承、保护继承、私有继承的区别
- C++ 公有继承、保护继承、私有继承的区别
- c++ 公有继承、保护继承和私有继承的区别
- C++中公有继承、保护继承、私有继承的区别
- 公有继承,私有继承,保护继承的区别
- C++中公有继承、保护继承、私有继承的区别
- C++公有继承、私有继承和保护继承的区别
- C++中公有继承、保护继承、私有继承的区别
- 公有继承,私有继承,保护继承的区别
- C/C++ 公有继承、保护继承和私有继承的区别
- 进程与线程的一个简单解释
- [C++]char* const char* std::string区分
- Qt和MFC的比较
- C/C++中判断某一文件或目录是否存在
- Struts功能详解——Struts控制流
- 从零开始学C++之继承(一):公有/私有/保护继承、overload/overwrite/override之间的区别
- C++标准库
- HDOJ--1010--Tempter of the Bone【DFS+剪枝】
- 【OpenCV】直方图应用:直方图均衡化,直方图匹配,对比直方图
- ActionBar神奇魅力2
- hdu 1018
- Ubuntu 13.04使用体验
- Jenkins的安装和使用
- android语音识别技术