C++:继承与多态(1)
继承: 继承是使代码可以复用的重要手段,也是面向对象程序设计的核心思想之一。
例子:
先看这样一段代码:
#include<iostream>
using namespace std;
class A
{
public:
A(int a=0):ma(a){}
private:
int ma;
};
class B :public A// :继承列表
{
public:
B(int b=0):mb(b){}
private:
int mb;
};
int main()
{
cout << sizeof(A) << endl << sizeof(B) << endl;
return 0;
}
打印结果:
可见,B继承了A的数据。解释如下
当基类、派生类有相同的成员变量时,派生类对象访问成员变量,访问的是派生类中的,若访问基类的需加上基类的访问限定。
#include<iostream>
using namespace std;
class A
{
public:
A(int a=0):ma(a){}
void Show()
{
cout << ma << endl;
}
public:
int ma;
};
class B :public A// :继承列表
{
public:
B(int b=0):ma(b){}
public:
int ma;
};
int main()
{
B b(10);
cout << b.A::ma << endl;
cout << b.ma << endl;
return 0;
}
打印结果:
继承了什么?
#include<iostream>
using namespace std;
class A
{
public:
A(int a=0):ma(a){}
void Show()
{
cout << ma << endl;
}
static void Print(A &lhs)
{
cout << lhs.ma << endl;
}
public:
int ma;
};
class B :public A
{
public:
B(int b=0):ma(b){}
public:
int ma;
};
int main()
{
A a(20);
B b(10);
b.Show();
b.Print(a);
return 0;
}
打印结果:
说明静态成员方法,普通成员方法都可以被继承。
那什么不可以被继承??
构造、析构、友元关系(父亲的朋友不是儿子的朋友)
继承的特点:
protected: 只允许在本类中,子类中访问。
private:只允许在本类中使用。
类和类的关系:
1.组合关系 has_a / apart of 桌腿是桌子的一部分
2.继承关系 is_a / a kind of 男人是人的一种
3.代理关系(容器、适配器的实现)
限制了底层的接口,对外提供了一种新的特性。
同名函数的关系:
1.重载: overlkoad
1) 同作用域
2)同名
3)参数列表不同
2. 隐藏: overhide
1)作用域不同、继承关系
2)隐藏了基类中所有的同名函数
3. 覆盖: override (虚函数)
代码解释:
#include<iostream>
using namespace std;
class Base//这个类中,两个Show()是重载关系
{
public:
Base(int a=0):ma(a){}
void Show()
{
cout << "Base::Show() "<< endl;
cout << ma << endl;
}
void Show(int rhs)
{
cout << "Base::Show(int)" << endl;
int sum = ma + rhs;
cout << sum << endl;
}
protected://可以扩展,且不能在类外访问
int ma;
};
class Derive :public Base
{
public:
Derive(int b):mb(b){}
void Show()
{
cout << "Derive::Show()" << endl;
cout << mb << endl;
}
private:
int mb;
};
int main()
{
Derive derive(10);
derive.Show();
//derive.Show(10);隐藏关系
//error C2660: “Derive::Show”: 函数不接受 1 个参数
derive.Base::Show(10);
return 0;
}
基类和派生类的构造和析构顺序:
#include<iostream>
using namespace std;
class Base//这个类中,两个Show()是重载关系
{
public:
//Base(){}
Base(int a):ma(a)
{
cout << "Base::Base() " << endl;
}
void Show()
{
cout << "Base::Show() "<< endl;
cout << ma << endl;
}
void Show(int rhs)
{
cout << "Base::Show(int)" << endl;
int sum = ma + rhs;
cout << sum << endl;
}
~Base()
{
cout << "Base::~Base()" << endl;
}
protected://可以扩展,且不能在类外访问
int ma;
};
class Derive :public Base
{
public:
Derive(int b):mb(b),Base(b)//指明了基类的构造方式
{
cout << "Derive::Derive() " << endl;
}
void Show()
{
cout << "Derive::Show()" << endl;
cout << mb << endl;
}
~Derive()
{
cout << "Derive::~Derive()" << endl;
}
private:
int mb;
};
int main()
{
Derive d(20);
return 0;
}
打印结果:
得出:先基类构造,后派生类构造。(先构造的后析构,后构造的先析构)
思考:基类和派生类的相互指向
int main()
{
Base* pb = new Derive(10);// 对
//Derive* pd = new Base(10);// 错
return 0;
}
总结:基类的指针可以指向派生类的对象,派生类的指针不可以指向基类的对象(不允许)
解释: 小范围可以指向大范围。