C++之普通成员函数、虚函数以及纯虚函数的区别与用法要点
普通成员函数是静态编译的,没有运行时多态,只会根据指针或引用的“字面值”类对象,调用自己的普通函数;虚函数为了重载和多态的需要,在基类中定义的,即便定义为空;纯虚函数是在基类中声明的虚函数,它可以再基类中有定义,且派生类必须定义自己的实现方法。 假设我们有三个类Person、Teacher、Student它们之间的关系如下:
类的关系图 普通成员函数 【Demo1】 #ifndef __OBJEDT_H__ #define __OBJEDT_H__ #include <string> #include <iostream> class Person { public: Person(const string& name,int age) : m_name(name),m_age(age) { } void ShowInfo() { cout << "姓名:" << m_name << endl; cout << "年龄:" << m_age << endl; } protected: string m_name; //姓名 int m_age; //年龄 }; class Teacher : public Person { public: Teacher(const string& name,int age,const string& title) : Person(name,age),m_title(title) { } void ShowInfo() { cout << "姓名:" << m_name << endl; cout << "年龄:" << m_age << endl; cout << "职称:" << m_title << endl; } private: string m_title; //职称 }; class Student : public Person { public: Student(const string& name,int studyId) : Person(name,m_studyId(studyId) { } void ShowInfo() { cout << "姓名:" << m_name << endl; cout << "年龄:" << m_age << endl; cout << "学号:" << m_studyId << endl; } private: int m_studyId; //学号 }; #endif //__OBJEDT_H__ 测试代码: void test() { Person* pPerson = new Person("张三",22); Teacher* pTeacher = new Teacher("李四",35,"副教授"); Student* pStudent = new Student("王五",18,20151653); pPerson->ShowInfo(); cout << endl; pTeacher->ShowInfo(); cout << endl; pStudent->ShowInfo(); cout << endl; delete pPerson; delete pTeacher; delete pStudent; } 结果: 姓名:张三 姓名:李四 姓名:王五 void test() { Person* pPerson = new Person("张三",22); Person* pTeacher = new Teacher("李四","副教授"); Person* pStudent = new Student("王五",20151653); pPerson->ShowInfo(); cout << endl; pTeacher->ShowInfo(); cout << endl; pStudent->ShowInfo(); cout << endl; delete pPerson; delete pTeacher; delete pStudent; } 结果: 姓名:张三 姓名:李四 姓名:王五 虚函数 我们把Person中的ShowInfo成员改成虚函数(在前面加上virtual),代码如下: class Person { public: Person(const string& name,m_age(age) { } virtual void ShowInfo() { cout << "姓名:" << m_name << endl; cout << "年龄:" << m_age << endl; } protected: string m_name; //姓名 int m_age; //年龄 }; 在执行上面【Demo2】中的测试代码,得到我们想到的结果: 姓名:张三 姓名:李四 姓名:王五
【Demo4】:针对第4点说明: class Person { public: Person(const string& name,m_age(age) { } virtual void ShowInfo() { cout << "姓名:" << m_name << endl; cout << "年龄:" << m_age << endl; } string GetName(); //正确,普通函数如果不被使用,可以只有声明没有定义 virtual int GetAge(); //错误,虚函数必须要有定义,即使是一个空实现,因为编译器无法确定会使用哪个函数 protected: string m_name; //姓名 int m_age; //年龄 }; 【Demo5】:针对第5点进行说明: class Person { public: virtual void SetAge(int age = 0) { m_age = age; } //... 省略 }; class Teacher : public Person { public: virtual void SetAge(int age = 1) { m_age = age; } //... 省略 }; class Student : public Person { public: virtual void SetAge(int age = 2) { m_age = age; } //... 省略 }; 测试1: void test() { Person* pPerson = new Person("张三",20151653); pPerson->SetAge(); pTeacher->SetAge(); pStudent->SetAge(); pPerson->ShowInfo(); cout << endl; pTeacher->ShowInfo(); cout << endl; pStudent->ShowInfo(); cout << endl; delete pPerson; delete pTeacher; delete pStudent; } 结果: 姓名:张三 姓名:李四 姓名:王五 void test() { Person* pPerson = new Person("张三",20151653); pPerson->SetAge(); pTeacher->SetAge(); pStudent->SetAge(); pPerson->ShowInfo(); cout << endl; pTeacher->ShowInfo(); cout << endl; pStudent->ShowInfo(); cout << endl; delete pPerson; delete pTeacher; delete pStudent; } 结果: 姓名:张三 姓名:李四 姓名:王五 在上面的例子中,我们假设所有的人都要工作,但不同的人工作的方式不同。于是我们就要强制要求继承自Person的子类都要有工作的方法,这就需要纯虚函数。定义如下: class Person { public: //... 省略 virtual void DoWork() = 0; //... 省略 }; 但此时我们编译 Person* pPerson = new Person("张三",22);
于是我们在子类中对它实现如下: class Teacher : public Person { public: //... 省略 virtual void DoWork() { cout << "教书..." << endl; } //... 省略 }; class Student : public Person { public: //... 省略 virtual void DoWork() { cout << "学习..." << endl; } //... 省略 }; 没用DoWork方法: void test() { Person* pTeacher = new Teacher("李四",20151653); pTeacher->DoWork(); cout << endl; pStudent->DoWork(); cout << endl; delete pTeacher; delete pStudent; } 结果: 教书… 学习…
通过以上对普通成员函数、虚函数以及纯虚函数的介绍,希望可以对大家有所帮助。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |