我现在正在课堂上学习C ++,但是我不太理解纯虚函数。 我知道它们稍后会在派生类中概述,但如果您只是要在派生类中定义它,为什么要将其声明为等于0?
我现在正在课堂上学习C ++,但是我不太理解纯虚函数。 我知道它们稍后会在派生类中概述,但如果您只是要在派生类中定义它,为什么要将其声明为等于0?
简而言之,这是为了使类成为抽象类,从而不能实例化,但可以通过子类重写纯虚方法来形成具体的类。这是在C++中定义接口的一种好方法。
这迫使派生类定义该函数。
class Foo {
// pure virtual, must be implemented by subclasses
virtual public void myMethod() = 0;
// normal method, will be available to all subclasses,
// but *can* be overridden
virtual public void myOtherMethod();
};
如果一个类中的每个方法都是抽象的,那么它可以被用作接口,要求所有子类通过实现其中包含的所有方法来遵循接口。
接口的一个示例:
class Bar {
// all method are pure virtual; subclasses must implement
// all of them
virtual public void myMethod() = 0;
virtual public void myOtherMethod() = 0;
};
C++中的纯虚方法基本上是一种定义接口而不需要实现它们的方法。
补充Steven Sudit的回答:
“简单来说,这是为了使类成为抽象类,从而防止其被实例化,但子类可以重写纯虚方法以形成具体类。这是在C++中定义接口的好方法。”
例如,如果您有一个基类(例如Shape),用于定义其派生类可以使用的许多成员函数,但希望防止声明Shape实例并强制用户仅使用派生类(可能是Rectangle、Triangle、Pentagon等)。
关于Jeff上面的回答:
非抽象类可以包含虚成员函数并被实例化。事实上,为了对成员函数进行重载,这是必需的,因为默认情况下C++不确定变量的运行时类型,但是当使用virtual关键字定义时,它会确定。
考虑以下代码(请注意,出于清晰起见,未包括访问器、修改器、构造函数等):
class Person{
int age;
public:
virtual void print(){
cout << age <<endl;
}
}
class Student: public Person{
int studentID
public:
void print(){
cout << age << studentID <<endl;
}
}
Person p = new Student();
p.print();
如果没有虚关键字,只会打印年龄,而不是像Student类应该打印出年龄和学生ID。
(此示例基于《C++ for Java程序员》中的一个非常相似的示例 http://www.amazon.com/Java-Programmers-Mark-Allen-Weiss/dp/013919424X)
@Steven Sudit:您完全正确,我忽略了实际继承,呃!为了保持清晰,访问器等未包含在内,我现在已经更明显地表达了这一点。 3-7-09:所有问题都已解决。
假设我想要建模几种形状,而且每种形状都有明确定义的面积。我决定每个形状都必须继承IShape
(“I”代表接口),并且IShape
将包括一个GetArea()
方法:
class IShape {
virtual int GetArea();
};
class IShape {
virtual int GetArea() = 0;
};
本质上,纯虚函数用于创建一个接口(类似于Java)。这可以用作两个模块(或类,或其他)之间就期望什么样的功能达成协议,而不需要知道另一部分的实现细节。这允许您使用相同的界面轻松插入和播放片段,而无需更改使用您的接口的其他模块中的任何内容。
例如:
class IStudent
{
public:
virtual ~IStudent(){};
virtual std::string getName() = 0;
};
class Student : public IStudent
{
public:
std::string name;
std::string getName() { return name; };
void setName(std::string in) { name = in; };
};
class School
{
public:
void sendStudentToDetention(IStudent *in) {
cout << "The student sent to detention is: ";
cout << in->getName() << endl;
};
};
int main()
{
Student student;
student.setName("Dave");
School school;
school.sendStudentToDetention(&student);
return 0;
}