代码重用
C++很重要的一个特征就是代码重用。在C语言中重用代码的方式是拷贝代码、修改代码。C++中可以用继承或组合的方式来重用。通过继承或组合现有的类来创建新类,而不是重新创建它们。
继承
1.继承是使用已经编写好的类来创建新类,新的类具有原有类的所有属性和操作,也可以在原有类的基础上做一些修改和增补。
2.新类称为派生类或子类,原有类称为基类或父类
3.派生类是基类的具体化。
派生类的声明语法为:
class 派生类名: 继承方式 基类名
{
派生类新增成员的声明;
}
公有、私有、保护继承
1.在关键字public后面声明,它们是类与外部的接口,任何外部函数都可以访问公有类型数据和函数。
2.在关键字protected后面声明,与private类似,其差别表现在继承与派生时对派生类的影响不同。
3.在关键字private后面声明,只允许本类中的函数访问,而类外部的任何函数都不能访问。
#include < iostream>
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 ;
}
private :
int a_;
} ;
class PrivateInherit : private Base
{
public :
void Test ( )
{
x_ = 10 ;
y_ = 20 ;
}
private :
int b_;
} ;
int main ( )
{
return 0 ;
}
默认继承保护级别
1. class Base {};
2. struct D1 : Base {}; // 公有继承
3. class D1 : Base {}; // 私有继承
接口继承与实现继承
1. 将类的公有成员函数称为接口。
2. 公有继承,基类的公有成员函数在派生类中仍然是公有的,换句话说是基类的接口成为了派生类的接口,因而将它称为接口继承。
3. 实现继承,对于私有、保护继承,派生类不继承基类的接口。派生类将不再支持基类的公有接口,它希望能重用基类的实现而已,因而将它称为实现继承。
继承与重定义
1. 对基类的数据成员的重定义。
2. 对基类的成员函数的重定义分为两种:
2.1 overwrite
与基类完全相同
与基类成员函数名相同,参数不同(会隐藏基类的函数)
2.2 override(覆盖)(虚函数再介绍)
继承与组合
1.无论是继承与组合本质上都是把子对象放在新类型中,两者都是使用构造函数的初始化列表去构造这些子对象。
2. 组合通常是希望在新类内部中具有已经存在类的功能时使用,而不是希望已存在的类作为它的接口。组合通过嵌入一个对象以实现新类的功能,而新类用户看到的时新定义的接口,而不是来自老类的接口。(has-a)
3. 如果希望新类与已存在的类有相同的接口(在这基础上可以增加自己的成员)。这时候需要用继承,也称为子类型化。(is-a)
#include < iostream>
using namespace std;
class Base
{
public :
Base ( ) : x_ ( 0 )
{
}
int GetBaseX ( ) const
{
return x_;
}
void Show ( )
{
cout << "Base::Show... " << endl;
}
int x_;
} ;
class Derived : public Base
{
public :
Derived ( ) : x_ ( 0 )
{
}
int GetDerivedX ( ) const
{
return x_;
}
void Show ( )
{
cout << "Derived::Show... " << endl;
}
void Show ( int n )
{
cout << "Derived::Show... " << n << endl;
}
int x_;
} ;
class Compose
{
public :
Base b_;
int x_;
} ;
int main ( )
{
Derived d;
d. x_ = 10 ;
d. Base: : x_ = 20 ;
cout << d. GetBaseX ( ) << endl;
cout << d. GetDerivedX ( ) << endl;
d. Show ( ) ;
d. Base: : Show ( ) ;
cout << sizeof ( Derived) << endl;
cout << sizeof ( Compose) << endl;
return 0 ;
}
不能自动继承的成员函数
1.构造函数
2.析构函数
3.=运算符
继承与构造函数
1.基类的构造函数不被继承,派生类中需要声明自己的构造函数
2.声明构造函数时,只需要对本类中新增成员进行初始化,对继承来的基类成员的初始化(调用基类构造函数完成)。
### 回顾还有哪些情况需要在构造函数初始化列表进行初始化。
#### const成员,引用成员
3.派生类的构造函数需要给基类的构造函数传递参数。
4. 基类------》派生类自身对象成员-------》派生类自身
#include < iostream>
using namespace std;
class ObjectB
{
public :
ObjectB ( int objb) : objb_ ( objb )
{
cout << "ObjectB ..." << endl;
}
~ ObjectB ( )
{
cout << "~ObjectB ..." << endl;
}
int objb_;
} ;
class ObjectD
{
public :
ObjectD ( int objd) : objd_ ( objd )
{
cout << "ObjectD ..." << endl;
}
~ ObjectD ( )
{
cout << "~ObjectD ..." << endl;
}
int objd_;
} ;
class Base
{
public :
Base ( int b, int objb) : b_ ( b) , objb_ ( objb )
{
cout << "Base ..." << endl;
}
Base ( const Base& other) : objb_ ( other. objb_) , b_ ( other. b_ )
{
}
~ Base ( )
{
cout << "~Base ..." << endl;
}
int b_;
ObjectB objb_;
} ;
class Derived : public Base
{
public :
Derived ( int b, int d, int ob, int od) : d_ ( d) , Base ( b, ob) , objd_ ( od )
{
cout << "Derived ..." << endl;
}
Derived ( const Derived& other) : d_ ( other. d_) , objd_ ( other. objd_) , Base ( other )
{
}
~ Derived ( )
{
cout << "~Derived ..." << endl;
}
int d_;
ObjectD objd_;
} ;
int main ( )
{
Derived d ( 200 , 100 , 300 , 400 ) ;
cout << d. d_ << endl;
cout << d. b_ << endl;
cout << d. objd_. objd_<< endl;
Base b ( 10 , 1 ) ;
Base b2 ( b) ;
cout << b2. b_ << endl;
Derived d2 ( d) ;
return 0 ;
}
友元关系与继承
友元关系不能被继承
### 回顾友元
#### 友元关系是不能被传递的,友元关系是单向的。
静态成员与继承
静态成员无所谓继承