c++学习笔记(12.继承与多态)(二)

2014-11-24 07:38:50 · 作者: · 浏览: 4
员的位置,也就是对象的地址就是VPTR指针的地址,当对象创建时,也就是调用了类的构造函数之后就创建了这个对象的虚函数表,此时就给VPTR指针进行了赋值,使其指向对象的虚函数表)。如果不是,编译器就可以直接调用本类型类的成员函数。 如图: \

示例代码:
#include 
   
    

using namespace std;
class parent
{
public:
	int a;
	virtual void fun()
	{
		cout << "parent fun()" <
    
     fun(); return 0; } 
    
   
注意: 出于效率的考虑,没有必要将所有成员函数都声明为虚函数。通过虚函数表指针VPTR调用重写函数是在 程序运行时进行的因此需要通过寻址操作才能确定真正应该调用的函数。而普通成员函数 是在编译时就确定了调用的函数。在效率上, 虚函数的效率要低很多。 c.虚函数与多态的关系: 多态是依靠虚函数实现的。但是就算我不想实现多态,依然可以在类中定义虚函数的,类创建对象时,依然产生虚函数表,依然存在VPTR指针。 d.对象在创建的时候由编译器对VPTR指针进行初始化,只有当对象的构造完全结束后VPTR的指向才最终确定,父类对象的VPTR指向父类虚函数表,子类对象的VPTR指向子类虚函数表。 e.构造函数中调用虚函数无法实现多态:说明下这个知识点,是本节的一个疑问。如果有大神路过,希望大神指点下。也希望再日后的学习中,自己可以补充上来!!!对于唐老师的 构造函数与VPTR指针之间的关系分析(唐老师的白板图)、还有那个this指针的举例的观点(唐老师的代码),我有所保留!!!待日后提高!!!这里面有一个不知对错的反例,代码如下:
#include 
   
    

using namespace std;

class parent
{
public:
	parent()
	{
	cout << "hello parent()" << endl;
	}
	virtual void fun()
	{
		cout << "parent fun() " <
    
     fun(); } void fun() { cout << "child fun() " << endl; } }; int main() { parent p; child c(&p); child c1(&c); } 
    
   
虽然不确定,但是依然记住构造函数中无法使用虚函数完成多态。

6.纯虚函数:

a.面向对象中的抽象类: 抽象类可以用于表示现实世界中的抽象概念。 抽象类是一种只能定义类型,而不能产生对象的类。 抽象类只能被继承并重写相关函数。抽象类的直接特征是纯虚函数。 b.纯虚函数: 只声明函数原型,而故意不定义函数体的虚函数 c.抽象类与纯虚函数: 第一: 抽象类不能定义对象(因为抽象类,就是利用继承,让自己这个父类的纯虚函数进行重写,使得多个子类产生多态的现象),抽象类的目的不是创建对象,而是使子类产生多态。 第二: 抽象类只能定义指针和引用 第三: 抽象类中的纯虚函数必须被子类重写 第四: 因为有纯虚函数的存在,所以类变成了抽象类,因为纯虚函数没有函数体且不能被调用,所以抽象类也不能定义对象(纯虚函数存在的目的,就是让抽象类的子类进行函数重写,从而实现多态),抽象类定义了对象就有可能调用纯虚函数! d.纯虚函数的示例:
class shape
{
public:
	virtual double area() = 0;
};
注意:area为纯虚函数,= 0 是告诉编译器,这个函数是纯虚函数,故意只声明不定义函数体
示例代码(这是一个很好的抽象类的例子,也是一个很不错的多态的例子):
#include 
   
    

using namespace std;

class Shape
{
public:
    virtual double area() = 0;
};

class Rectangle : public Shape
{
    double m_a;
    double m_b;
public:
    Rectangle(double a, double b)
    {
        m_a = a;
        m_b = b;
    }
    
    double area()
    {
        return m_a * m_b;
    }
};

class Circle : public Shape
{
    double m_r;
public:
    Circle(double r)
    {
        m_r = r;
    }
    
    double area()
    {
        return 3.14 * m_r * m_r;
    }
};

void area(Shape* s)
{
    cout<
    
     area()<