在C++里至少含有一个纯虚函数的类为抽象类,在以前的印象里纯虚函数只能声明在基类,不能在基类实现。
先来复习一下纯虚函数长什么样子
virtual void func() =0;
//virtual 返回类型 函数名(参数1,参数2,```) =0;
答案是:
1. 在子类中实现了纯虚函数(实现就是按照原函数的声明,加上函数体,返回类型,参数类型、参数个数等均不能改变),
那么这个子类就不是抽象类,而是一个具体类,可以创建该类的实例对象,子类要实现抽象类的纯虚方法需要先在类定义里声明;
2. 子类继承抽象基类,如果在定义里没有声明基类的纯虚方法,则默认不实现基类的纯虚方法,该子类依旧是抽象类,不能实例化对象。
图中CollegeStudent类继承了Person类,但没有实现Person类的纯虚方法,在实例化时就出现图中所示错误。
综上所述:
与java对比了一下发现在java里使用abstract声明的抽象类与C++里使用 vittual 声明的纯虚函数的抽象类是有挺大区别的。
在java里抽象类里声明的抽象方法是不允许有实现的,实现一定要在子类里。而在C++里的类似于抽象方法的纯虚函数,抽象类是可以有实现的!
以下是验证代码:
#pragma once
#ifndef PERSON_H_
#define PERSON_H_
#include
using namespace std;
class Person
{
public:
Person();
Person(int Age,string Sex,string Name);
~Person();
int getAge();
string getName();
string getSex();
virtual void show() = 0;
void print();
virtual void updateAge()
{
cout << "Person类的updateAge方法:" << endl;
cout << this->name << "的年龄原来为" << this->age << endl;
age = age + 1;
cout << this->name << "的年龄现在为" << this->age << endl;
}
private:
string name;
int age;
string sex;
};
#endif // !PERSON_H_
#include "stdafx.h"
#include
#include"person.h"
using namespace std;
void Person::show()
{
cout << "调用Person类的抽象虚方法show,我的调用证明了完全虚函数是可以有实现并且可以被调用的" << endl;
cout << this->name << "信息如下:" << endl;
cout << "年龄:" << this->age << " 性别:" << this->sex << endl<void Person::print()
{
cout << this->name << "信息如下:" << endl;
cout << "年龄:" << this->age << " 性别:" << this->sex << endl;
}
Person::Person()
{
this->age = 19;
this->name = "张三";
this->sex = "男";
}
Person::Person(int Age, string Sex, string Name)
{
this->age = Age;
this->name = Name;
this->sex = Sex;
}
Person::~Person()
{
}
int Person::getAge()
{
return age;
}
string Person::getSex()
{
return sex;
}
string Person::getName()
{
return name;
}
#pragma once
#ifndef STUDENT_H_
#define STUDENT_H_
#include
#include
#include "person.h"
using namespace std;
class Student : public Person
{
public:
Student();
Student(int Age, string Sex, string Name);
Student(int Age, string Sex, string Name,int Sno,string School);
~Student();
int getSno() { return sno; };
string getSchool() { return school; };
void show();
void updateAge();
private:
int sno;
string school;
};
void Student::show()
{
cout << "Student类的show方法:" << endl;
this->print();
cout << "学号:" << this->sno << " 就读学校:" << this->school << endl << endl;
}
Student::Student()
{
this->sno = 100;
this->school = "BeiJingUniversity";
}
Student::Student(int Age, string Sex, string Name) :Person(Age,Sex,Name)
{
this->sno = 100;
this->school = "BeiJingUniversity";
}
Student::Student(int Age, string Sex, string Name, int Sno, string School):Person(Age, Sex, Name)
{
this->school = School;
this->sno = Sno;
}
Student::~Student()
{
}
void Student::updateAge()
{
cout << "我是Student类里重写的虚方法updateAge\n\n";
}
#endif // !STUDENT_H_
#pragma once
#ifndef COLLEGESTUDENT_H_
#define COLLEGESTUDENT_H_
#include
#include
#include "person.h"
using namespace std;
class CollegeStudent :public Person
{
public:
CollegeStudent();
~CollegeStudent();
void introduce()
{
cout << "大学生来自**大学" << endl;
}
private:
string major;
};
CollegeStudent::CollegeStudent()
{
}
CollegeStudent::~CollegeStudent()
{
}
#endif // !COLLEGESTUDENT_H_
#include "stdafx.h"
#include<iostream>
#include "person.h"
#include "Student.h"
#include "collegeStudent.h"
using namespace std;
int main()
{
Student *student = new Student();
student->show();
student->updateAge();
cout << endl;
Person *person = new Student(45, "男", "李白",102,"南方科技大学");
person->Person::show();
person->updateAge();
cout << endl;
Student *test = new Student(45, "男", "曹操",101,"基因大学");
test->Person::show();
test->Person::updateAge();
cout << endl;
//CollegeStudent *cs = new CollegeStudent();
return 0;
}
从运行结果可以发现纯虚函数在抽象类定义里是除了声明之外也是可以实现的,
并且通过子类实例化父类得到的对象可以通过显式地调用抽象基类的纯虚方法,甚至子类对象显式调用抽象基类的纯虚方法都是允许的。
只用virtual关键字声明的方法为虚方法,可以被继承,继承后可以进行重载,也可以不重载。
B *test=new C();
test->f();
上面的情况调用f()实际上调用的是对象C最近重载的f()方法。