人生苟且了很长时间,须要再继续努力了。面试
总结了C++的继承方面的关系:编程
朋友在面试的时候被问过一个问题,说类的继承重要的一点是什么,他没有答到点子上,后来面试官提到的是代码的复用,不用每次都从新写相同的代码,仍是有道理的。框架
类的声明:函数
class TableTennisPlayer
{
private:
string firstname;
string lastname;
bool hashTable;设计
public:
TableTennisPlayer(const string &fn = "none", const string &ln = "none", bool ht=false);
void Name() const; //只读的一个函数
bool HashTable() const {return hashTable;};
bool ResetTable (bool v) { hashTable = v;};指针
};对象
初始化:继承
TableTennisPlayer play1("zhang", "jingle", true);内存
string firstname;
string lastname;
bool hashTable;字符串
原型是这样的
TableTennisPlayer(const string &fn = "none", const string &ln = "none", bool ht=false);
由此引伸出来的一点,写字符串的过程当中的赋值过程,应该是调用了 string 类的 以const char *做为参数的构造函数。若是是以string 类为参数的话,则会调用
等等,有一点没有想明白,形参为const string &, 若是传递的参数类型的是string 的话,调用的构造函数是几回?,若是传入的参数类型是const char*的话,调用的构造参数又是几回?
我感受这方面仍是没有理清楚??
在派生一个类中,以下所示,增长了一个成员变量,对于
class RatedPlayer: public TableTennisPlayer
{
private:
unsigned int rating;
public:
//想起来了,是基本的构造函数
RatedPlayer(unsigned int r = 0, const string &fn = "none", const string &ln = "none", bool ht = false);
//是复制构造函数
RatedPlayer(unsigned int r, const TableTennisPlayer &tp);
unsigned int Rating() const {return rating;};
void Reseat (unsigned int r){rating = r;};
};
派生类的构造函数,
一、首先建立基类对象
二、派生类的构造函数经过成员初始化列表将基类的信息传递给基类构造函数。(这个分状况,可能调用基类的构造函数,默认构造函数和复制构造函数)
三、派生类的构造函数应初始化派生类新增的数据成员。
基类的私有部分也是派生类的一部分,可是只能经过基类的公有和保护方法来进行访问。访问权限也是很重要的。
基类和派生类的关系:
一、派生类可使用基类的方法,这个方法不能是私有的。
二、基类指针能够在不进行显示转换的状况下指向派生类,基类引用能够在不显示转换的状况下,引用派生类对象(向上强制转换,不能将派生类的指针指向派生类)
可是上面基类的指针却只能调用基类的方法。
例子:
class base
{
};
class bigger::public base
{
}
bigger hh;
base &rt = hh;
base *rt2 = &hh;
就是这么简单。
基类指针若是想要调用派生类的方法
一、虚函数
virtual void test()
{
printf("test.....");
};
若是只是虚函数的话,在基类中是要实现的。
在派生类中能够不用从新实现这个类,若是在派生类中没有实现,则调用基类的方法。若是在派生类从新实现了该方法,则调用的时候使用派生类的方法。
二、纯虚函数
纯虚函数 virtual test() = 0;
这个是须要在派生类中必需要实现的,带有纯虚函数的基类是不能直接使用的,只是做为一个框架在使用,目的就是让别人继承实现多态。
class base
{
public:
virtual dddd() = 0;
};
base aaa; 这样是不能够的。
class bigger ::public base
{
public:
dddd()
{
xxxxxxxxxx;
}
};
bigger bbbb ;这样是能够的。
C++中,多态的这种机制才是精华,访问权限的控制。
若是基类中的数据和方法是privated:
在派生类中,只能调用 基类的方法来访问基类的访问权限
虚函数的几种状况,
一、基类中为虚函数
基类中对虚函数有定义,有实现。
想验证一下那种是错误的写法:
1.1 派生类 中 对虚函数有定义,带virtual 无实现
不能够。
1.2派生类中对虚函数有定义,带virtual 有实现
调用派生类中的方法。
1.3派生类中对虚函数有定义,不带virtual 无实现
不能够
1.4 派生类中对虚函数有定义,不带virtual 有实现
调用派生类中方法。
1.4 派生类中对虚函数无定义,不实现。
结果是调用基类的方法。这个是最基本的。
总结一下就是想要在派生类中修改就必定要有定义和实现,感受本身写的是废话,可是定义带不带virtual 是否是同样呢??
本身纠结了这么长时间的问题,百度了一下就知道了,不是必须的,可是为了代码的清晰易读,仍是加上吧,为了让孙子类知道,这个是虚函数,呵呵
二、基类中为纯虚函数。
基类中不须要实现,可是在派生类中必需要实现。
三、 当虚函数赶上重载。
简单
class dwelling
{
public:
virtual void showperks() const ;
virtual void showperks(int a)const ;
};
class hovel:public dwelling
{
public:
virtual void showperks() const;
virtual void showperks(int a)const ;//若是此方法注释的话,也不能调用基类中的该方法,基类中其余版本被隐藏了。
};
当重载赶上虚函数时,想要在派生类中对基类中的函数想要修改的话,就必须在派生类中进行所有从新定义,所有实现。
具体见:/learnCpluseplus/inherit/brass/test1.cpp 。
多态的是实现有两种方式:
一、一种就是派生类中从新定义基类方法。
二、使用虚函数。
在 上面的例子中 用基类指针指向派生类,若是在基类中定义了一个虚函数,而且在派生类中实现的话(派生类中无论实现的为virtual 仍是非virtual ),用基类指针调用该函数,则会调用到派生类中的方法。
看的C++中总结的术语:
若是方法是经过引用或者指针而不是对象调用的,它将肯定使用哪一种方法,若是没有使用关键字virtual ,程序将只用引用类型或者是指针类型选择方法,若是使用了virtual,程序将根据引用或指针指向的对象的类型来选择方法。
class
派生类中国访问权限的控制:
C++中的权限分为public、protected、private,继承的方式也有三种,分别是public、protected、private这三种方式
通俗讲,派生类中某个属性或者方法的权限,就是基类中的访问权限与继承访问权限的较小集。(也就是数学中的交集)
在C++中,编译器对于方法,是静态联编仍是动态联编,是跟方法是否认义为虚函数有关系的,编译器对非虚方法使用的是静态联编,对于虚方法是使用动态联编。
虚函数的工做原理:
对每个对象都保存一个隐藏的指针,隐藏的指针指向虚函数表。
若是派生类中对基类中的虚函数进行了从新实现,则派生类的虚函数表保存新的函数的地址,
若是派生类中没有对基类中的虚函数实现,则派生类的虚函数表扔保存基类中的地址。
class base
{
public:
virtual void printA();
virtual void printB()
}
class ::public base
{
void printB();
virtual void printC();
};
总结一点,虚函数实现机制比较好,可是内存和执行速度会有必定的成本。
抽象基类:
这个是一种很高深的能力,在设计基类的时候应该先构建出出编程中所须要的类,以及他们之间的关系,抽象基类更清晰、复杂度更低,在基于组件的编程模型中很常见。
继承和内存中的分配,这个刚开始没有搞清楚,固然如今也没有搞清楚。
抽象能力。